/** * @brief Check if any chstat process is listening. Bailout if not. */ static void ipc_require_listener(void) { /* While we are in the mutual exclusive section, we don't listen to signals, because it would be hard to reset the state of the mutex */ sigset_t blocked_signals, curr_set; (void) sigfillset(&blocked_signals); (void) sigprocmask(SIG_BLOCK, &blocked_signals, &curr_set); /* Mutual exclusive section so no other process removes shm segment meanwhile */ if(semdown(mtx) == -1) { bail_out(EXIT_FAILURE, "Error downing mutex"); } /* Do we have any listeners? */ if((shared->flag & READER_F) != 1) { (void) semup(mtx); // Because ipc_shutdown() tries to down the mutex bail_out(EXIT_SUCCESS, "No chstat process listening."); } /* Release Mutex */ if(semup(mtx) == -1) { bail_out(EXIT_FAILURE, "Error downing mutex"); } /* Reset to original procmask*/ (void) sigprocmask(SIG_SETMASK, &curr_set, NULL); }
void lock_release (lock_ptr l) { if (l->next_count > 0) { semup (l->next); } else { semup (l->mutex); } }
void cond_wait (cond_ptr cnd) { cnd->sem_count++; if (cnd->the_lock->next_count > 0) { semup (cnd->the_lock->next); } else { semup (cnd->the_lock->mutex); } semdown (cnd->cond_sem); cnd->sem_count--; }
void lock_release (struct lock *l) { assert (l != NULL); if(l->nextCount > 0) { // l->nextCount -= 1; SHOULD NOT BE HERE!!! semup (l->next); //// MISSING!!!!!!!!! } else { semup(l->mutex); } }
void writer (int mutex, int writing, int priority, int writerid) { FILE *wtimefile; long randnum, compare; struct timeval tv; struct timezone tz; gettimeofday(&tv, NULL); // wait for a certain amount of time... // wtimefile = fopen("wtimefile", "r"); // if (wtimefile == NULL) // { // // create the file then open it again // fclose(wtimefile); // wtimefile = fopen("wtimefile", "w"); // fprintf(wtimefile, "0\n"); // fclose(wtimefile); // wtimefile = fopen("wtimefile", "r"); // } srandom((tv.tv_usec / 100) + (tv.tv_sec * 100)); randnum = random() % 200000; if (randnum < 20000) { randnum += 20000; } // fscanf(wtimefile, "%ld", &compare); // fclose(wtimefile); // if (compare == randnum) // { // randnum = random() % 200000; // if (randnum < 20000) // { // randnum += 20000; // } // } // // write new random number to file // rtimefile = fopen("rtimefile", "w"); // fprintf(rtimefile, "%ld\n", randnum); // fclose(rtimefile); printf("writer %d entering waiting state for %ld microseconds\n", writerid, randnum); usleep(randnum); semdown(priority); semdown(writing); // write some stuff printf ("writer %d is currently writing\n", writerid); semup(writing); semup(priority); printf ("writer %d is finished writing\n", writerid); }
//// // gender_one // // // void gender_one (char *exec, int id, int *line, int mutex, int depends, int group, int reproducing, int raising) { int one = 0; // hide misleading index number int gathered; // shared variable FILE *fp; // file pointer for gathered shared variable file // print entering waiting state printf ("alien %d of gender 1 beginning to wait in line\n", id); // begin sleeping for random time dowait (1); // semdown (line[one]); // line_1.down() semdown (group); // group.down() semdown (mutex); // mutex.down() // get the shared gathered variable from "aliengathvar" fp = fopen ("aliengathvar", "r"); // print error if could not open file successfully if (fp < 0 || fp == NULL) { fprintf (stderr, "%s: %s: failed to open aliengathvar\n", exec, "ERROR"); exit (-1); } fscanf (fp, "%d", &gathered); // scan shared variable fclose (fp); // close read file // increment gathered gathered += 1; // check if the last of three gender residents necessary to reproduce if (gathered == 3) { gathered = 0; // attained group size so reset semdown (reproducing); // one of two groups to begin reproducing // all three have "reached" barrier semup (depends); semup (depends); semup (depends); } // write the shared variable gathered to "aliengathvar" fp = fopen ("aliengathvar", "w"); if (fp < 0 || fp == NULL) { fprintf (stderr, "%s: %s: failed to open aliengathvar\n", exec, "ERROR"); exit (-1); } fprintf (fp, "%d\n", gathered); // write shared variable fclose (fp); // close write file // semup (mutex); // mutex.up() semdown (depends); // depends.down() semup (group); // group.up() // print entering reproducing state printf ("alien %d of gender 1 beginning to reproduce\n", id); // hit sleeping barrier semdown (raising); // raising.down() printf ("%s %d of gender 1: leaving nursery\n", "alien", id); // leaving nursery }
void gender3(){ int val1 = semvalue(1); int val2 = semvalue(2); int up, down; if ((val1 == 1001)||semvalue(1)==1001){ down = semdown(3); }else { up = semup(1); up = semup(2); up = semup(4); repTIME = rand()%200000+2000; usleep(repTIME); int time = rand()%40000+1000; usleep(time); } }
/** Print out character statistics */ static void print_stat(void) { /* While we are in the mutual exclusive section, we don't listen to signals, because it would be hard to reset the state of the mutex */ sigset_t blocked_signals, curr_set; (void) sigfillset(&blocked_signals); (void) sigprocmask(SIG_BLOCK, &blocked_signals, &curr_set); /* Mutual exclusive section so no other process removes shm segment meanwhile */ if(semdown(mtx) != -1) { /* Print per letter stat */ for(int i = 0; i <= ASCII_CHAR_MAX; ++i) { (void) fprintf(stdout, " %c: %d\t%d%%\n", i + ASCII_CHAR_OFFSET, shared->stat[i], (shared->total == 0 ? 0 : shared->stat[i] * 100 / shared->total)); } /* Print 'others' stat */ (void) fprintf(stdout, "%s: %d\t%d%%\n", "andere", shared->stat[ASCII_CHAR_MAX + 1], (shared->total == 0 ? 0: shared->stat[ASCII_CHAR_MAX + 1] * 100 / shared->total)); /* Print total stat */ (void) fprintf(stdout, "%s: %d\t%d%%\n", "gesamt", shared->total, 100); (void) semup(mtx); } /* Reset to original procmask*/ (void) sigprocmask(SIG_SETMASK, &curr_set, NULL); }
int main (int argc, char **argv) { char *exec = argv[0]; if (argc < 3) { fprintf (stderr, "%s: %s: need a test id and semaphore id\n", "ERROR", exec); fprintf (stderr, "%s: ./testup [testID] [semaphoreID]\n", "USAGE"); return -1; } int testid = atoi (argv[1]); int semid = atoi (argv[2]); // test semup printf ("%s %d: %s: %d\n", exec, testid, "beginning semup", semid); int result = semup (semid); if (result <= 0) { fprintf (stderr, "%s %d: %s: in %s\n", exec, testid, "ERROR", "semup"); return result; } printf ("%s %d: %s: %d\n", exec, testid, "finished semup", semid); // finished all printf ("%s %d: %s\n", exec, testid, "finished all"); return result; }
/* what does this program do? First we make a semaphore check what its value is do semdown on it start sleep 10 seconds -> at this point, another program would try to semdown the semaphore we created end sleep now do a semup, program B should be able to proceed. -> program C should now free the semaphore, and try a semvalue on it. */ int main() { int result; int e; message m; e = errno; printf("+-----------------+\n"); printf("| Program A Start |\n"); printf("+-----------------+\n"); result = seminit(2000, 1); printf("<1> Create semaphore named 2000, with value 1: result=%d & e=%d\n", result, errno); result = semvalue(2000); printf("<2> Look at value of semaphore[index for indentifier(2000)]: result=%d & e=%d\n", result, errno); result = semdown(2000); printf("<3> Do a sem down: result=%d & e=%d\n", result, errno); printf("<4> I am to do nothing for 10 seconds.\n"); int wait_unit; for (wait_unit = 1; wait_unit < 11; wait_unit++) { sleep(1); printf(" Waiting %d\n", wait_unit); } printf("<4> I done doing nothing.\n"); result = semup(2000); printf("<5> Sem Up: result=%d & e=%d\n", result, errno); printf("<6> Program A has no more to do.\n", result, errno); return 0; }
int mod_rwlock(A_UNUSED int argc,A_UNUSED char *argv[]) { if((startsem = semcrt(READERS + WRITERS)) < 0) error("Unable to create start-sem"); if(rwcrt(&lck) < 0) error("Unable to create rw-lock"); for(int i = 0; i < WRITERS; ++i) { if(startthread(thread_write,NULL) < 0) error("Unable to start reader-thread"); } for(int i = 0; i < READERS; ++i) { if(startthread(thread_read,NULL) < 0) error("Unable to start reader-thread"); } /* go! */ for(int i = 0; i < READERS + WRITERS; ++i) semup(startsem); join(0); if(curval != WRITERS * RETRIES) printe("Something went wrong. curval should be %d, but is %d\n",WRITERS * RETRIES,curval); rwdestr(&lck); return 0; }
int sys_semup(void) { int sem_id; argint(0,&sem_id); return semup(sem_id); }
void cond_signal (cond_ptr cnd) { if (cnd->sem_count > 0) { cnd->the_lock->next_count++; semup (cnd->cond_sem); semdown (cnd->the_lock->next); cnd->the_lock->next_count--; } }
void gender2(){ int val1 = semvalue(1); int val3 = semvalue(3); int down, up; if ((val1 == 1001)&&(val3 == 1001)){ down = semdown(2); }else { int nursVAL = semvalue(4); while (nursVAL == 1001); up = semup(2); up = semup(3); while (repTIME == 0); usleep(repTIME); int time = rand()%4000000+1000; usleep(time); } }
void cond_signal (struct cond *cnd) { assert (cnd != NULL); if(cnd->semCount > 0) { cnd->lock->nextCount += 1; semup(cnd->condSem); } }
/** * Write buffer to shared memory * * @param data buffer to write to shared memory * * @return -1 on error, 0 otherwise */ static int ipc_write(char *data) { int ret = -1; /* It makes no sense to proceed if nobody is listening */ ipc_require_listener(); /* * Firts wait for write queue to let us in * if cnd or mt are no valid semaphores anymore, another process has already removed them. so we will simply return -1 */ if(msemdown(cnd, 1, 0) != -1) { /* While we are in the mutual exclusive section, we don't listen to signals, because it would be hard to reset the state of the mutex */ sigset_t blocked_signals, curr_set; (void) sigfillset(&blocked_signals); (void) sigprocmask(SIG_BLOCK, &blocked_signals, &curr_set); /* Mutual exclusive section so no other process removes shm segment meanwhile */ if(semdown(mtx) != -1) { if(data == NULL) { /* Signal EOF to Listener */ shared->flag |= EOF_F; } else { for(int i = 0; i <= MAX_BUF_SIZE; ++i) { shared->data[i] = data[i]; /* Null char */ if(data[i] == 0) { break; } } } ret = (semup(mtx) == -1 ? -1 : 0); } /* Reset to original procmask*/ (void) sigprocmask(SIG_SETMASK, &curr_set, NULL); /* Signal read queue to proceed */ ret = (msemup(cnd, 1, 1) == -1 ? -1 : 0); } return ret; }
/** * Cleanup all ipc resources */ static void ipc_shutdown(void) { /* We need to block all signals to avoid race condition */ sigset_t blocked_signals; (void) sigfillset(&blocked_signals); (void) sigprocmask(SIG_BLOCK, &blocked_signals, NULL); /* cleanup has already been done */ if(cleanup == 1) { return; } cleanup = 1; /* If cnd has already been aquired, try to remove it (would return -1 if cnd had already been removed by other process) */ if(cnd != -1) { (void) msemrm(cnd); } /* detach SHM Segment (So it can be free'd later, or by other process) */ shm_detach(); if(mtx != -1) { /* This fails with -1 if onother process has already done the cleanup of smh segment */ if(semdown(mtx) != -1) { /* * It might happen, that we only fail to aquire shm segment, but have a working mtx. * In this case we will not destroy the mtx, because other processes might have created an shm segment and will therefor need a working mtx to free it. */ if(shm != -1) { (void) shmctl(shm, IPC_RMID, NULL); (void) semrm(mtx); } else { (void) semup(mtx); } } } }
/** Initialize all variables needed for ipc */ static void ipc_init(void) { /* All communicating processes need to be started from within the ssame working dir in order to make key have the same value */ key_t key = ftok(".", 'x'); if(key == -1) { bail_out(EXIT_FAILURE, "Couldn't create ipc key via ftok"); } /* cnd is a two field semaphore (0 = write, 1 = read)*/ if((cnd = mseminit(key, (0600), 2, 1, 0)) == -1) { if((cnd = msemgrab(key, 2)) == -1) { bail_out(EXIT_FAILURE, "Error aquiring conditional semephores"); } } /* mtx is a mutex semaphore to protect access to shm */ if((mtx = seminit(key + 1, (0600), 0)) == -1) { if((mtx = semgrab(key + 1)) == -1) { bail_out(EXIT_FAILURE, "Error aquiring mutual exclusive semephore"); } } /* Create or fetch shm segment */ if((shm = shmget(key, sizeof(ipc_data_t), IPC_CREAT | IPC_EXCL | (0600))) == -1) { if((shm = shmget(key, sizeof(ipc_data_t), 0)) == -1) { bail_out(EXIT_FAILURE, "Error aquiring shared mem"); } /* The process that creates the shm segment will up the mtx, after it's initialized */ if(semdown(mtx) == -1) { bail_out(EXIT_FAILURE, "Error downing mutex"); } /* Mount shm */ if((shared = shmat(shm, NULL, 0)) == (void *) -1) { bail_out(EXIT_FAILURE, "Error attaching shm segment"); } #ifndef _BUILD_READIN /* Signal listening reader */ shared->flag |= READER_F; #endif /* Let other processes proceed */ if(semup(mtx) == -1) { bail_out(EXIT_FAILURE, "Error upping mutex"); } } else { /* Mount shm */ if((shared = shmat(shm, NULL, 0)) == (void *) -1) { bail_out(EXIT_FAILURE, "Error attaching shm segment (creator)"); } /* If we created the segment, we'll initialize it */ (void) memset(shared, 0, sizeof(ipc_data_t)); #ifndef _BUILD_READIN /* Signal listening reader */ shared->flag |= READER_F; #endif /* And signal other processes to proceed */ if(semup(mtx) == -1) { bail_out(EXIT_FAILURE, "Error opening mutex"); } } }
/** * Read shared data and calculate statistics * * @return -1 on error, 0 on EOF, number of read chars otherwise */ static int ipc_process(void) { int i = -1; /* * First, wait for read queue to let us in * if cnd or mt are no valid semaphores anymore, another process has already removed them. so we will simply return -1 */ if(msemdown(cnd, 1, 1) != -1) { /* While we are in the mutual exclusive section, we don't listen to signals, because it would be hard to reset the state of the mutex */ sigset_t blocked_signals, curr_set; (void) sigfillset(&blocked_signals); (void) sigprocmask(SIG_BLOCK, &blocked_signals, &curr_set); /* Mutual exclusive section so no other process removes shm segment meanwhile */ if(semdown(mtx) != -1) { i = 0; /* EOF Flag has been set, return 0 */ if((shared->flag & EOF_F) != 1) { for(i = 0; i <= MAX_BUF_SIZE; ++i) { int c; /* Null character */ if(shared->data[i] == 0) { break; } /* We will only distinguish between uppercase'd chars */ c = toupper(shared->data[i]) - ASCII_CHAR_OFFSET; if(c < 0 || c > ASCII_CHAR_MAX) { /* No Ascii Letter -> inc 'others' counter */ shared->stat[ASCII_CHAR_MAX + 1]++; } else { /* inc letter counter */ shared->stat[c]++; } /* Total number of characters */ shared->total++; /* Clear out buffer */ shared->data[i] = 0; } } if(semup(mtx) == -1) { i = -1; } } /* Reset to original procmask*/ (void) sigprocmask(SIG_SETMASK, &curr_set, NULL); /* Let write queue proceed */ if(msemup(cnd, 1, 0) == -1) { i = -1; } } return i; }