int unlock_sem(CAPI_LOCK_TYPE_E type) { int semid, value; struct sembuf op; memset(&op, '\0', sizeof(struct sembuf)); semid = get_semid(); if(semid == -1) { DEBUG_PRINTF("get_semid failed\n"); return -1; } value = semctl(semid, type, GETVAL, 0); if (value != 0) { DEBUG_PRINTF("unlock failed, lock_type = [%s], bad/current sem value = [%d]\n", CAPI_LOCK_NAME_MAP[type], value); return -1; } op.sem_num = type; op.sem_op = 2; /* op.sem_flg = SEM_UNDO;*/ op.sem_flg = 0; if(semop(semid, &op, 1) == -1) { DEBUG_PRINTF("semop failed\n"); return -1; } return 0; }
int lock_sem(CAPI_LOCK_TYPE_E type) { int semid, value; struct sembuf op[2]; memset(&op[0], '\0', sizeof(struct sembuf)); memset(&op[1], '\0', sizeof(struct sembuf)); semid = get_semid(); if(semid == -1) { DEBUG_PRINTF("get_semid failed\n"); return -1; } op[0].sem_num = type; op[0].sem_op = -2; op[0].sem_flg = SEM_UNDO; op[1].sem_num = type + 1; op[1].sem_op = -2; op[1].sem_flg = SEM_UNDO; if(semop(semid, &op, 2) == -1) { DEBUG_PRINTF("semop failed\n"); return -1; } value = semctl(semid, type, GETVAL, 0); if(value != 0) { DEBUG_PRINTF("value is not zero[%d]\n", value); } return 0; }
/** * Acts as a withdraw process */ void withdraw(int request) { int semid = get_semid((key_t)SEMAPHORE_KEY); int shmid = get_shmid((key_t)SEMAPHORE_KEY); struct shared_variable_struct *shared_variables = shmat(shmid, 0, 0); // wait(mutex) printf("PID: %d - Someone is waiting on mutex to withdraw $%d.\n", getpid(), request); semaphore_wait(semid, SEMAPHORE_MUTEX); printf("PID: %d - Withdrawer:%d has passed mutex.\n", getpid(), request); // if (wcount = 0 and balance > withdraw) if (shared_variables->wcount == 0 && shared_variables->balance >= request) { // {balance = balance - withdraw; signal(mutex)} printf("PID: %d - A withdrawal of $%d was made!\n", getpid(), request); shared_variables->balance = shared_variables->balance - request; printf("PID: %d - Withdrawer:%d is signaling mutex.\n", getpid(), request); print_memory(shared_variables); semaphore_signal(semid, SEMAPHORE_MUTEX); } else { // wcount = wcount + 1; shared_variables->wcount = shared_variables->wcount + 1; // AddEndOfList(LIST, withdraw); printf("PID: %d - Withdrawer:%d is added to queue.\n", getpid(), request); insertLast(shared_variables->list, request); if (shared_variables->list->head == NULL) { printf("Totally null\n"); } // signal(mutex); printf("PID: %d - Withdrawer:%d is signaling mutex.\n", getpid(),request); semaphore_signal(semid, SEMAPHORE_MUTEX); print_memory(shared_variables); // wait(wlist); printf("PID: %d - Withdrawer is waiting to withdraw.\n", getpid()); semaphore_wait(semid, SEMAPHORE_WLIST); printf("PID: %d - Withdrawer is now ready to withdraw.\n", getpid()); // balance = balance - FirstRequestAmount(LIST); shared_variables->balance = shared_variables->balance - getFirstRequestAmount(shared_variables->list); //printf("%d\n", shared_variables->balance); // DeleteFirstRequest(LIST); removeFirst(shared_variables->list); // wcount = wcount - 1; shared_variables->wcount = shared_variables->wcount - 1; // if (wcount > 1 and (FirstRequestAmount(LIST)) < balance)) signal(wlist) if (shared_variables->wcount > 0 && getFirstRequestAmount(shared_variables->list) < shared_variables->balance) { printf("PID: %d - Withdrawer is signaling the next withdrawer.\n", getpid()); print_memory(shared_variables); semaphore_signal(semid, SEMAPHORE_WLIST); } // else signal(mutex)} else { printf("PID: %d - Withdrawer is signaling mutex.\n", getpid()); print_memory(shared_variables); semaphore_signal(semid, SEMAPHORE_MUTEX); } } if (shmdt(shared_variables) == -1) { perror("shmdt failed during a withdraw"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int size = 0; int shared_memory_key = -1; int sem_r = -1; int sem_w = -1; int cnt = -1; int buf = -1; int *shared_memory = NULL; errno = 0; /* check command line arguments */ if ((size = check_arguments(argc, argv))==ERROR) { print_usage(); return ERROR; } /* get both semaphores */ if((shared_memory_key = get_shmem(SHMEMKEY, size)) == -1) { clean_up(sem_r, &shared_memory, shared_memory_key, ERROR); return ERROR; } attach_shmem(shared_memory_key, &shared_memory, SEMKEY_R); if(shared_memory == NULL) { clean_up(sem_r, &shared_memory, shared_memory_key, ERROR); return ERROR; } /* initialize shared memory */ if((sem_r= get_semid(SEMKEY_R, 0)) == ERROR) { clean_up(sem_r, &shared_memory, shared_memory_key, ERROR); return ERROR; } /* attach memory to process */ if((sem_w= get_semid(SEMKEY_W, size))==ERROR) { clean_up(sem_r, &shared_memory, shared_memory_key, ERROR); return ERROR; } /* start the reader */ do { if(P(sem_r)==-1) { if(errno == EINTR) { /*EINTR sagt uns, dass ein Interrupt vorliegt. */ errno = 0; continue; } else { clean_up(sem_r, &shared_memory, shared_memory_key, ERROR); fprintf(stderr, "Error bei P, reader. %s", strerror(errno)); return ERROR; } } cnt++; cnt = cnt%size; buf = (*(shared_memory+cnt)); if(V(sem_w)==-1) { if(errno == EINTR) { /*EINTR sagt uns, dass ein Interrupt vorliegt. */ errno = 0; continue; } else { clean_up(sem_r, &shared_memory, shared_memory_key, ERROR); fprintf(stderr, "Error bei V, reader. %s", strerror(errno)); return ERROR; } } if(buf!=EOF) { /* Do ouput and check for Output error */ if (fputc(buf, stdout) == EOF) { fprintf(stderr, "Fehler fputc"); clean_up(sem_r, &shared_memory, shared_memory_key, ERROR); return ERROR; } } }while(buf!=EOF); errno = 0; if(fflush(stdout)!=0) { fprintf(stderr, "fflush failed"); if(errno != 0) { fprintf(stderr, "%s", strerror(errno)); return ERROR; } } detach_shmem(shared_memory_key,SEMKEY_R); clean_up(sem_r, &shared_memory, shared_memory_key, SEMKEY_R); return 0; }