#include "libnazgul.h" #include "ids.h" /* TODO: remplacer le bool de msgPoolData par un identifiant de semaphore. Le semaphore contient poolNb valeurs (et indique donc le nombre de ressources disponnibles). */ /* TODO: prevoir le cas des négatifs dans la taille ... */ void *msgAllocate(msgSpace * space, int pool, int taille, int option) { void *resultAddr = NULL; int bufferFreeSize; int i; msgPoolId resultPoolId; /* tableau des valeurs des semPoolCoef/pool pour identifier le pool * qui sera libéré le plus rapidement */ float semPoolCoef[space->poolNb]; int idxPoolOptimum; bool gotRessourceSem; msgPoolDataTabSemId ressourceSemId; sem_t *ressourceSemFd; int ressourceSemVal; int nbLockedSem; float minPoolCoef; int selectedPoolIndex; int bufferFreeIndex; msgPoolData *mSPoolDataTabAddr; selectedPoolIndex = -1; mSPoolDataTabAddr = msgPoolDataTabOpen(space); if (mSPoolDataTabAddr == NULL) { NZG_ERROR("msgPoolDataTabOpen", space->poolDataTabId); goto ERROR; } /* // verifier le premier arg du shm_open mSPoolDataTabFd=shm_open(space->poolDataTabId, O_RDWR, MSGSPACE_DEFAULT_MODE); if (mSPoolDataTabFd == -1 ) { fprintf( stderr, "Allocate %s failed: %s\n", (char*)space->poolDataTabId, strerror( errno ) ); return NULL; } mSPoolDataTabAddr = mmap( 0, (space->poolNb) * sizeof( msgPoolData ), PROT_READ | PROT_WRITE, MAP_SHARED, mSPoolDataTabFd, 0 ); if( mSPoolDataTabAddr == MAP_FAILED) { fprintf( stderr, "mmap failed: %s\n", strerror( errno ) ); return NULL; } */ gotRessourceSem = false; /* initialisation des coefs */ for (i = 0; i < (space->poolNb); i++) { semPoolCoef[i] = -1; } nbLockedSem = 0; if (pool == ANYPOOL) { fprintf(stderr, "[ ALLOCATION ANYPOOL : %d ]\n", (int)getpid()); // choisir le pool au hasard (ou presque) for (i = 0; i < (space->poolNb); i++) { printf("- boucle %d\n", i); fflush(stdout); if (mSPoolDataTabAddr[i].bufferSize >= taille) { printf("( buffSize > taille )\n"); fflush(stdout); /* choisir le numero du semaphore en fonction du nombre de lock poses / nombre de buffer */ msgPoolSemIdIntern(ressourceSemId, space->id, i); ressourceSemFd = sem_open(ressourceSemId, O_CREAT, SEM_DEFAULT_MODE, 0); if (ressourceSemFd == SEM_FAILED) { NZG_ERROR("sem_open", ressourceSemId); return NULL; } /* on remplit le tableau avec les valeurs des semaphores */ if (sem_getvalue (ressourceSemFd, &ressourceSemVal) < 0) { NZG_ERROR("sem_getvalue", ressourceSemId); return NULL; } printf("RESSOURCESEMVAL %d\n", ressourceSemVal); if (ressourceSemVal <= 0) { printf("resVal < 0 : %d\n", ressourceSemVal); /* il y a ressourceSemVal processus qui attendent déja... */ semPoolCoef[nbLockedSem] = (float)((1 - ressourceSemVal) / mSPoolDataTabAddr[i]. bufferNb); nbLockedSem++; } if (sem_trywait(ressourceSemFd) == 0) { printf("got try_wait\n"); /* choisir la 1ere pool de taille plus grande * libre si possible */ gotRessourceSem = true; selectedPoolIndex = i; break; } if (sem_close(ressourceSemFd) < 0) { NZG_ERROR("sem_getvalue", ressourceSemId); return NULL; } } // if buffSize > taille } // for printf("ERRORDETECT outFor\n"); fflush(stdout); if (!gotRessourceSem) { printf("Calcul du meilleur en cas de liberation\n"); minPoolCoef = semPoolCoef[0]; idxPoolOptimum = 0; /* on cherche le pool avec le moins de lock poses / nbre de buffer * le numéro du pool est stocké dans idxPoolOptimum */ for (i = 0; i < nbLockedSem; i++) { printf("Coef %d : %d\n", i, (int)semPoolCoef[i]); if ((semPoolCoef[i] != -1) && (semPoolCoef[i] < minPoolCoef)) { minPoolCoef = semPoolCoef[i]; idxPoolOptimum = i; } } if (minPoolCoef == -1) { /* il n'y a aucune pool dont la taille satisfait la demande */ return NULL; } else { selectedPoolIndex = idxPoolOptimum; } printf("Optimum : %d\n", selectedPoolIndex); } } else { fprintf(stderr, "[ ALLOCATION : %d ]\n", (int)getpid()); selectedPoolIndex = pool; } if (!gotRessourceSem) { msgPoolSemIdIntern(ressourceSemId, space->externId, selectedPoolIndex); ressourceSemFd = sem_open(ressourceSemId, O_CREAT, SEM_DEFAULT_MODE, 0); if (ressourceSemFd == SEM_FAILED) { NZG_ERROR("sem_open", ressourceSemId); return NULL; } //TODO:virer la ligne suivante: sem_getvalue(ressourceSemFd, &ressourceSemVal); printf("SemWait... %s : %d\n", ressourceSemId, ressourceSemVal); if (sem_wait(ressourceSemFd) < 0) { NZG_ERROR("sem_wait", ressourceSemId); sem_close(ressourceSemFd); return NULL; } printf("Passed %s\n", ressourceSemId); } /* on a acqui un semaphore pour la ressouce */ /* on acquiert le droit de modifier les infos sur la ressource */ /* on protege le tableau des associations */ msgPoolDataTabLock(space); /* on modifie maintenant les données */ /* - on récupere l'index du premier buffer libre */ bufferFreeIndex = msgBufferGetFreeIndex(mSPoolDataTabAddr, selectedPoolIndex); if (bufferFreeIndex < 0) { // aucun buffer libre ? NZG_ERROR("msgBufferGetFreeIndex", ""); goto ERROR; } printf("Buffer selected : %d,%d\n", selectedPoolIndex, bufferFreeIndex); /* mapper le buffer libre dans l'esp addr du proc */ strcpy(resultPoolId, mSPoolDataTabAddr[selectedPoolIndex].poolId); bufferFreeSize = mSPoolDataTabAddr[selectedPoolIndex].bufferSize; printf("BufferSize : %d\n", bufferFreeSize); resultAddr = msgBufferMap(mSPoolDataTabAddr, selectedPoolIndex, bufferFreeIndex); if (resultAddr == NULL) { NZG_ERROR("msgBufferMap", mSPoolDataTabAddr[selectedPoolIndex].poolId); goto ERROR; } /* - on s'enregistre aupres de ce buffer */ msgBufferAttachProc(mSPoolDataTabAddr, selectedPoolIndex, bufferFreeIndex, resultAddr); // munmap(mSPoolDataTabAddr,(space->poolNb) * sizeof( msgPoolData )); /* unmapper le msgPoolDataTab */ msgPoolDataTabClose(space, mSPoolDataTabAddr); msgPoolDataTabUnlock(space); printf("alloc de %p\n", (void *)resultAddr); return resultAddr; ERROR: NZG_ERROR("msgAllocate", "error processing"); msgPoolDataTabUnlock(space); munmap(mSPoolDataTabAddr, (space->poolNb) * sizeof(msgPoolData)); return NULL; }