static int lock_sem(int sid) { int member = 0; struct sembuf sem_lock={ 0, -1, IPC_NOWAIT}; int success = 0; //printf("locking sem, member count = %d\n", get_sem_member_count(sid) ); /* Attempt to lock the semaphore set */ int semval = get_sem_val(sid, member); if(semval > 0) { sem_lock.sem_num = member; if((semop(sid, &sem_lock, 1)) != -1) { success = 1; } } return success; }
static int unlock_sem(int sid) { int member = 0; struct sembuf sem_unlock={ member, 1, IPC_NOWAIT}; /* will fail if we can't can't unlock semaphore for some reason, * will NOT fail if semaphore is already unlocked */ int success = 1; /* Is the semaphore set locked? */ int semval = get_sem_val(sid, member); if(semval == 0) { /* it's locked, unlock it */ sem_unlock.sem_num = member; success = ((semop(sid, &sem_unlock, 1)) == -1) ? 0 : 1; } return success; }
int main(int argc, char ** argv){ key_t key; int *shm_seg, shm_id, sem_id, pid, fd_fifo; int i, tmp, count_r; int r_arr[2]; unsigned int nn, n, size; struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigchldhandler; if (sigaction(SIGCHLD, &sa, 0) < 0){ perror("sigaction"); exit(0); } printf("n: "); scanf("%u", &n); if (n < 2){ printf("n must be bigger than 1\n"); exit(0); } nn = 2; while (nn < n){ nn <<= 1; } /*-initialize*/ if (mknod(FIFO, S_IFIFO | 0660, 0) < 0){ perror("mknod: "); exit(2); } if ((key = ftok(argv[0], 'q')) < 0) { perror("ftok"); exit(2); }/*========================================================================*/ size = nn*sizeof(int); if ((shm_id = open_seg(key,size)) < 0){ printf("open_seg error\n"); exit(2); } if (*(shm_seg = shmat(shm_id, 0, 0)) < 0) { printf("error attaching %d\n",shm_id); exit(2); } if ((sem_id = open_sem(key,4)) < 0){ printf("open_sem error\n"); exit(2); } srand(key); for(i = 0; i < n; i++){ shm_seg[i] = rand() % 100; printf("%d ", shm_seg[i]); } for(; i < nn; i++){ shm_seg[i] = 100; printf("%d ", 100); } printf("\n"); /*=initialize*/ op_sem(sem_id, &r_unlock[0]); op_sem(sem_id, &w_unlock[0]); for(i = 0; i < nn/2; i++){ if ((pid = fork()) < 0){ printf("fork %d", i); exit(0); } if (pid == 0){ if ((fd_fifo = open(FIFO, O_RDONLY | O_NONBLOCK)) < 0){ if (errno == EINTR){ _exit(0); } perror("open2: "); _exit(2); } while (get_sem_val(sem_id, 3) > 0){ r_arr[0] = 0; r_arr[1] = 0; /* trouble: В конце работы read читает из пустой фифо. Надо найти макс задержку read'а. Или семафоры...:( */ op_sem(sem_id, &r_lock[0]); if ((count_r = read(fd_fifo, &r_arr, sizeof(int)*2)) < 0){ if (errno == EAGAIN){ continue; } perror("read: "); _exit(2); }; if (count_r < 2){ continue; } op_sem(sem_id, &iter_unlock[0]); op_sem(sem_id, &r_unlock[0]); if (shm_seg[r_arr[0]] > shm_seg[r_arr[1]]){ tmp = shm_seg[r_arr[0]]; op_sem(sem_id, &w_lock[0]); shm_seg[r_arr[0]] = shm_seg[r_arr[1]]; shm_seg[r_arr[1]] = tmp; op_sem(sem_id, &w_unlock[0]); } } printf("die.\n"); if (close(fd_fifo) < 0){ perror("close2"); } _exit(0); } } while (1){ if ((fd_fifo = open(FIFO, O_WRONLY | O_NONBLOCK)) < 0){ if (errno == EINTR || errno == ENXIO){ continue; } perror("open3: "); exit(0); }else{ break; } } op_sem(sem_id, &work_start[0]); make_mn(nn, nn, 1, fd_fifo, sem_id); op_sem(sem_id, &work_stop[0]); if (close(fd_fifo) < 0){ perror("close2"); }; for(i = 0; i < n; i++){ printf("%d ", shm_seg[i]); } printf("\n"); while(die < nn/2); detach_seg((char *)shm_seg); close_seg(shm_id); close_sem(sem_id); return 0; }