#include "libnazgul.h" #include "nzg_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 i, mSPoolDataTabFd; 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; sem_t * poolDataTabSemFd; msgPoolDataTabSemId ressourceSemId; sem_t * ressourceSemFd; int ressourceSemVal; int nbLockedSem; float minPoolCoef; int selectedPoolIndex; int bufferFreeIndex; int mSPoolFd; msgPoolData * mSPoolDataTabAddr; selectedPoolIndex=-1; /* TODO: 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; iid,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 */ poolDataTabSemFd=sem_open(space->poolDataTabSemId, O_CREAT,SEM_DEFAULT_MODE,1); if (poolDataTabSemFd == SEM_FAILED){ NZG_ERROR("sem_open : ouverture de la ressource", space->poolDataTabSemId); return NULL; } sem_wait(poolDataTabSemFd); /* on modifie maintenant les données */ /* - on récupere l'index du premier buffer libre */ bufferFreeIndex = msgBufferGetFreeIndex(mSPoolDataTabAddr,selectedPoolIndex); if (bufferFreeIndex < 0){ sem_close(poolDataTabSemFd); // aucun buffer libre ? return NULL; } printf("Buffer selected : %d,%d\n",selectedPoolIndex,bufferFreeIndex); /* mapper le buffer libre dans l'esp addr du proc */ strcpy(resultPoolId,mSPoolDataTabAddr[selectedPoolIndex].poolId); mSPoolFd=shm_open(resultPoolId,O_RDWR,MSGSPACE_DEFAULT_MODE); resultAddr = mmap( 0, mSPoolDataTabAddr[selectedPoolIndex].bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, mSPoolFd, 0 ); //TODO: /* - on s'enregistre aupres de ce buffer */ msgBufferAttachProc(mSPoolDataTabAddr, selectedPoolIndex, bufferFreeIndex, resultAddr); close(mSPoolFd); sem_post(poolDataTabSemFd); sem_close(poolDataTabSemFd); /* TODO: unmapper le msgPoolDataTab */ return resultAddr; }