l3.libnazgul/src/allocate.c

226 lines
6.3 KiB
C

#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;
}