#include #include #include #include #include #include #include #include #include #include #include void init_shm(void); /*******************************************************************/ /*******************************************************************/ #define REST_TIME 50 #define WORK_TIME 100 #define MAXT 100 #define SHOVELS 3 //lopaty SEM_ID semShovels; //hromada hliny SEM_ID semSoilHeap; //counter lock SEM_ID semLock; //tasky HOLE int idHole[MAXT]; int idHoleCount=0; //tasky UPPER int idUpper[MAXT]; int idUpperCount=0; //status int statusHole[MAXT]; int statusUpper[MAXT]; //showels int shovelHole[MAXT]; int shovelUpper[MAXT]; /*******************************************************************/ /*******************************************************************/ struct company { char name[20]; int work; }; struct company_registry { struct company companies[50]; }; struct company_registry *ptr; SEM_ID lock; //struct company *actualCompany; int actualCompany; const struct timespec rqrp = {0,1000000}; int company(); /*******************************************************************/ /** * Create new company */ int main(int argc, char *argv[]) { int i; //WATCH if( argc==1 ) { init_shm(); //need for memory access while(1) { printf("\nStatus:\n"); for(i=0; i<50; i++) //go trought all companies { if( ptr->companies[i].name[0]!='\0' ) //NOT EMPTY { printf("Company %s status: %d\n",ptr->companies[i].name, ptr->companies[i].work); } } //sleep nanosleep(&rqrp, NULL); //micro -> mili -> 1s } //COMPANY }else{ //create company init_shm(); semTake(lock,WAIT_FOREVER); //for ever //register to memory for(i=0; i<50; i++) { //find first empty place if( ptr->companies[i].name[0]=='\0' ) { //check length //if( str_len(argv[1])>10 )break; //register strcpy(ptr->companies[i].name,argv[1]); ptr->companies[i].work = 0; //actualCompany = &ptr->companies[i]; actualCompany = i; break; } } semGive(lock); //run company company(); } return 0; } void init_shm(void) { int fd; int first=0; /* Obtain an interprocess lock to protect manipulation with shared memory */ lock = semOpen("/company-lock", SEM_TYPE_MUTEX, SEM_FULL, SEM_Q_FIFO, OM_CREATE, NULL); /* use semTake() and semGive() to protect some code below */ semTake(lock,WAIT_FOREVER); /* or consider using O_EXCL flag to find the first use of shared memory */ fd = shm_open("/company", O_RDWR | O_CREAT | O_EXCL, S_IRUSR|S_IWUSR); if( fd==-1 ) { //create 2+ fd = shm_open("/company", O_RDWR | O_CREAT, S_IRUSR|S_IWUSR); }else{ first=1; } /* set the size of shared memory block */ if (ftruncate (fd, sizeof(struct company_registry)) == -1) { perror("ftruncate"); exit (1); } /* Map shared memory object in the address space of the process */ ptr = (struct company_registry *)mmap(0, sizeof(struct company_registry), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == (struct company_registry *)MAP_FAILED) { semGive(lock); exit (1); } /* close the file descriptor; the mapping is not impacted by this */ close (fd); /* ... */ /* the fist company has to zero the memory this way: */ if( first==1 )memset(ptr, 0, sizeof(struct company_registry)); /* ... register this company to the memory ... */ semGive(lock); } /*******************************************************************/ /*******************************************************************/ /*******************************************************************/ /*******************************************************************/ /*******************************************************************/ /*******************************************************************/ /*******************************************************************/ /*******************************************************************/ //DOLNI KOPAC int checkHole(int n, int state) { if( statusHole[n]==-1 )return 0; return 1; } void digger_in_hole(int n) { while (1) { int ret; taskSafe(); ret=semTake(semShovels, 1000); //vezmu lopatu if( ret!=0 ) { if( checkHole(n, 0)==1 ) { taskUnsafe(); //zkusime znovu continue; }else{ taskUnsafe(); //konec return; } } shovelHole[n]=1; printf("In hole %d: working\n", n); taskDelay(WORK_TIME); semGive(semSoilHeap); //nahazu hlinu //Inkrementuju counter semTake(semLock, WAIT_FOREVER); //nevadí, nemůže se tady smazat - vždy to projde ptr->companies[actualCompany].work++; semGive(semLock); //tyto dve instrukce musi byt atomicke => unsafe az po nich semGive(semShovels); //vratim lopatu shovelHole[n]=0; taskUnsafe(); printf(">In hole %d: resting\n", n); taskDelay(REST_TIME); if( checkHole(n, 0)==0 ) return; } } /*******************************************************************/ //HORNI NAKLADAC int checkUpper(int n, int state) { if( statusUpper[n]==-1 )return 0; return 1; } void digger_upper(int n) { while (1) { int ret; taskSafe(); ret=semTake(semShovels, 1000); //vezmu lopatu if( ret!=0 ) { if( checkUpper(n, 0)==1 ) //zkusim znovu { taskUnsafe(); continue; }else{ taskUnsafe(); //konec return; } } shovelUpper[n]=1; ret=semTake(semSoilHeap, 1000); //odhazim hlinu if( ret!=0 ) { if( checkUpper(n, 0)==1 ) { semGive(semShovels); //vratim lopatu - zkusim znovu ziskat a zacit kopat shovelUpper[n]=0; taskUnsafe(); continue; }else{ //konec semGive(semShovels); //vratim lopatu shovelUpper[n]=0; taskUnsafe(); return; } } printf("Upper %d: working\n", n); taskDelay(WORK_TIME); //opet musi byt atomicke nasledujici dve volani semGive(semShovels); //vratim lopatu shovelUpper[n]=0; taskUnsafe(); printf("Upper %d: resting\n", n); taskDelay(REST_TIME); if( checkUpper(n, 0)==0 ) return; } } /*******************************************************************/ //CREATE DIGGERS void createDiggerInHole() { statusHole[idHoleCount]=0; shovelHole[idHoleCount]=0; idHole[ idHoleCount ]=taskSpawn("Digger in hole "+idHoleCount, 210, 0, 4096, (FUNCPTR) digger_in_hole, idHoleCount, 0, 0, 0, 0, 0, 0, 0, 0, 0); printf("In hole %d: created\n", idHoleCount); idHoleCount++; } void createDiggerUpper() { statusUpper[idUpperCount]=0; shovelUpper[idUpperCount]=0; idUpper[ idUpperCount ]=taskSpawn("Digger in hole "+idUpperCount, 210, 0, 4096, (FUNCPTR) digger_upper, idUpperCount, 0, 0, 0, 0, 0, 0, 0, 0, 0); printf("Upper %d: created\n", idUpperCount); idUpperCount++; } /*******************************************************************/ //REMOVE DIGGERS void removeDiggerUpper() { int i=idUpperCount-1; int s; printf("Upper %d: deletion\n", i); taskDelete(idUpper[ i ]); printf("Upper %d: deleted\n", i); //vracime az po ukonceni tasku - mezitim ji mohl vratit task sam s=shovelUpper[i]; if( s==1 )semGive(semShovels); //vratim lopatu idUpperCount--; } void removeDiggerInHole() { int i=idHoleCount-1; int s; printf("Hole %d: deletion\n", i); taskDelete(idHole[ i ]); printf("Hole %d: deleted\n", i); //vracime az po ukonceni tasku - mezitim ji mohl vratit task sam s=shovelHole[i]; if( s==1 )semGive(semShovels); //vratim lopatu idHoleCount--; } /*******************************************************************/ //KONEC void endOfRun() { int i; int ch=idHoleCount; int cu=idUpperCount; printf("ENDING...\n"); for(i=0; icompanies[actualCompany].name[0]='\0'; // printf("ENDED\n"); } /*******************************************************************/ //INIT int company() { semSoilHeap = semCCreate(SEM_Q_FIFO, 0); // zatim zadna hlina semShovels = semCCreate(SEM_Q_FIFO, SHOVELS); // k dispozici N lopat semLock = semCCreate(SEM_Q_FIFO, 1); // binární semafor printf("INITIALIZED\n"); //vytvorime zakladni dvojici pracovniku createDiggerInHole(); createDiggerUpper(); //read input while(1) { switch( getchar() ) { case 'P': createDiggerUpper(); break; case 'p': createDiggerInHole(); break; case 'O': removeDiggerUpper(); break; case 'o': removeDiggerInHole(); break; case 'K': case 'k': endOfRun(); //exit return 0; } } }