int main(){ int id; /* Number by which the semaphore is known within a program */ /* The next thing is an argument to the semctl() function. Semctl() does various things to the semaphore depending on which arguments are passed. We will use it to make sure that the value of the semaphore is initially 0. */ union semun { int val; struct semid_ds *buf; ushort * array; } argument; argument.val = 1; /* Create the semaphore with external key KEY if it doesn't already exists. Give permissions to the world. */ id = semget(KEY, 1, 0666 | IPC_CREAT); /* Always check system returns. */ if(id < 0) { fprintf(stderr, "Unable to obtain semaphore.\n"); exit(0); } /* What we actually get is an array of semaphores. The second argument to semget() was the array dimension - in our case 1. */ /* Set the value of the number 0 semaphore in semaphore array # id to the value 0. */ if( semctl(id, 0, SETVAL, argument) < 0) { fprintf( stderr, "Cannot set semaphore value.\n"); } else { fprintf(stderr, "Semaphore %d initialized.\n", KEY); } int pid=fork(); if(pid){ struct sembuf operations[1]; int retval; /* Return value from semop() */ /* Get the index for the semaphore with external name KEY. */ id = semget(KEY, 1, 0666); if(id < 0){ /* Semaphore does not exist. */ fprintf(stderr, "Program sema cannot find semaphore, exiting.\n"); exit(0); } operations[0].sem_num = 0; /* Which operation? Subtract 1 from semaphore value : */ operations[0].sem_op = -1; /* Set the flag so we will wait : */ operations[0].sem_flg = 0; while(1){ //Process 1 //wait operations[0].sem_op = -1; retval = semop(id, operations, 1); //critical section printf("In critical section P1 ... \n"); fflush(stdout); int stime=2+(rand()/(float)(RAND_MAX))*4; printf("Sleeping for %d secs\n",stime); sleep(stime); printf("Ending critical section P1 ... \n"); fflush(stdout); operations[0].sem_op = 1; //signal retval = semop(id, operations, 1); } }else{ //Process 2 struct sembuf operations[1]; int retval; /* Return value from semop() */ /* Get the index for the semaphore with external name KEY. */ id = semget(KEY, 1, 0666); if(id < 0){ /* Semaphore does not exist. */ fprintf(stderr, "Program sema cannot find semaphore, exiting.\n"); exit(0); } operations[0].sem_num = 0; /* Which operation? Subtract 1 from semaphore value : */ operations[0].sem_op = -1; /* Set the flag so we will wait : */ operations[0].sem_flg = 0; while(1){ //wait operations[0].sem_op = -1; retval = semop(id, operations, 1); //critical section printf("In critical section P2 ... \n"); fflush(stdout); int stime=2+(rand()/(float)(RAND_MAX))*4; printf("Sleeping for %d secs\n",stime); sleep(stime); printf("Ending critical section P2 ... \n"); fflush(stdout); //signal operations[0].sem_op = 1; retval = semop(id, operations, 1); } } }
int main(int argc, char* argv[]) { union semun arg; /* used to set semaphore parameters */ struct sembuf sembuf; /* used to do a wait and signal */ int semID; /* the shared memory id */ int flags; /* flags for semget() call */ /* check command line args */ if((argc != 2) || (argv[1][0] != 'p' && argv[1][0] != 'c')) { fprintf(stderr, "Usage: a.out {p|c}\n"); fprintf(stderr, "Where:\n"); fprintf(stderr, "\tp: Producer (Start second)\n"); fprintf(stderr, "\tc: Consumer (start first)\n"); exit(1); } flags = PERMS|IPC_CREAT; /* system calls to create the semaphore */ semID = semget(KEY, 1, flags); /* create 1 semaphore in set (index 0) */ if(semID < 0) { perror(">>> ERROR! Consumer must be started first."); exit(1); } if(argv[1][0] != 'p') { /* initialize the semaphore */ arg.val = 0; /* initalize semphore to 0 */ if(semctl(semID, 0, SETVAL, arg) < 0) { perror (">>> ERROR! Initialization failed."); exit(1); } } if(argv[1][0] == 'p') { /* Producer does a semsignal() */ fprintf(stdout, "Producer signaling....\n"); sembuf.sem_num = 0; /* first sem in set */ sembuf.sem_op = 1; /* 1 means signal */ sembuf.sem_flg = 0; if(semop(semID, &sembuf, 1) == -1) { perror(">>> ERROR! Signal failed."); exit(1); } } else { /* Consumer does a semwait() */ fprintf(stdout, "Consumer waiting ....\n"); sembuf.sem_num = 0; /* first sem in set */ sembuf.sem_op = -1; /* -1 means wait */ sembuf.sem_flg = 0; if(semop(semID, &sembuf, 1) == -1) { perror(">>> ERROR! Wait failed"); exit(1); } fprintf(stdout, "Producer has signaled.\n"); /* delete */ if(semctl(semID, 0, IPC_RMID, arg) == -1) { perror(">>> ERROR! Unsuccessful delete"); exit(1); } } fprintf(stdout, "Done.\n"); return 0; }
void *mm_core_create(size_t usersize, const char *file) { mem_core *mc; void *area = ((void *)-1); #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE) || defined(MM_SHMT_IPCSHM) int fdmem = -1; #endif int fdsem = -1; #if defined(MM_SEMT_IPCSEM) int fdsem_rd = -1; #endif #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) char *fnmem; #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) char *fnsem; #endif size_t size; #if defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) int zero = 0; #endif #if defined(MM_SHMT_IPCSHM) struct shmid_ds shmbuf; #endif #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) char shmfilename[MM_MAXPATH]; #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) char semfilename[MM_MAXPATH]; #endif #if defined(MM_SHMT_BEOS) area_id temparea; #endif char filename[MM_MAXPATH]; if (usersize <= 0 || usersize > mm_core_maxsegsize()) { errno = EINVAL; return NULL; } if (file == NULL) { sprintf(filename, MM_CORE_DEFAULT_FILE, (int)getpid()); file = filename; } mm_core_init(); size = mm_core_align2page(usersize+SIZEOF_mem_core); #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) sprintf(shmfilename, "%s.mem", file); fnmem = shmfilename; #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) sprintf(semfilename, "%s.sem", file); fnsem = semfilename; #endif #if defined(MM_SHMT_MMANON) if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0)) == (void *)MAP_FAILED) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map anonymous area"); #endif /* MM_SHMT_MMANON */ #if defined(MM_SHMT_BEOS) if ((temparea = create_area("mm", (void*)&area, B_ANY_ADDRESS, size, B_LAZY_LOCK, B_READ_AREA|B_WRITE_AREA)) < 0) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to create the memory area"); #endif /* MM_SHMT_BEOS */ #if defined(MM_SHMT_MMPOSX) shm_unlink(fnmem); /* Ok when it fails */ if ((fdmem = shm_open(fnmem, O_RDWR|O_CREAT|O_EXCL, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open tempfile"); if (ftruncate(fdmem, mm_core_mapoffset+size) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to truncate tempfile"); write(fdmem, &zero, sizeof(zero)); if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map tempfile"); shm_unlink(fnmem); close(fdmem); fdmem = -1; mm_core_mapoffset += size; #endif /* MM_SHMT_MMPOSX */ #if defined(MM_SHMT_MMZERO) if ((fdmem = open("/dev/zero", O_RDWR, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open /dev/zero"); if (lseek(fdmem, mm_core_mapoffset+size, SEEK_SET) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to seek in /dev/zero"); write(fdmem, &zero, sizeof(zero)); if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map /dev/zero"); close(fdmem); fdmem = -1; mm_core_mapoffset += size; #endif /* MM_SHMT_MMZERO */ #if defined(MM_SHMT_MMFILE) unlink(fnmem); if ((fdmem = open(fnmem, O_RDWR|O_CREAT|O_EXCL, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open memory file"); if (ftruncate(fdmem, mm_core_mapoffset+size) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to truncate memory file"); write(fdmem, &zero, sizeof(zero)); if ((area = (void *)mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fdmem, mm_core_mapoffset)) == (void *)MAP_FAILED) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to memory map memory file"); close(fdmem); fdmem = -1; mm_core_mapoffset += size; #endif /* MM_SHMT_MMFILE */ #if defined(MM_SHMT_IPCSHM) if ((fdmem = shmget(IPC_PRIVATE, size, (SHM_R|SHM_W|IPC_CREAT))) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire shared memory segment"); if ((area = (void *)shmat(fdmem, NULL, 0)) == ((void *)-1)) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to attach shared memory"); if (shmctl(fdmem, IPC_STAT, &shmbuf) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to get status of shared memory"); shmbuf.shm_perm.uid = getuid(); shmbuf.shm_perm.gid = getgid(); if (shmctl(fdmem, IPC_SET, &shmbuf) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set status of shared memory"); if (shmctl(fdmem, IPC_RMID, NULL) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to remove shared memory in advance"); #endif /* MM_SHMT_IPCSHM */ #if defined(MM_SEMT_FLOCK) unlink(fnsem); if ((fdsem = open(fnsem, O_RDWR|O_CREAT|O_EXCL, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file"); #if defined(F_SETFD) && defined(FD_CLOEXEC) if (fcntl(fdsem, F_SETFD, FD_CLOEXEC) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set close-on-exec flag"); #endif #endif /* MM_SEMT_FLOCK */ #if defined(MM_SEMT_FCNTL) unlink(fnsem); if ((fdsem = open(fnsem, O_RDWR|O_CREAT|O_EXCL, MM_CORE_FILEMODE)) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to open semaphore file"); #if defined(F_SETFD) && defined(FD_CLOEXEC) if (fcntl(fdsem, F_SETFD, FD_CLOEXEC) == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to set close-on-exec flag"); #endif #endif /* MM_SEMT_FCNTL */ #if defined(MM_SEMT_IPCSEM) fdsem = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR); if (fdsem == -1 && errno == EEXIST) fdsem = semget(IPC_PRIVATE, 1, IPC_EXCL|S_IRUSR|S_IWUSR); if (fdsem == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore"); mm_core_semctlarg.val = 0; semctl(fdsem, 0, SETVAL, mm_core_semctlarg); fdsem_rd = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR); if (fdsem_rd == -1 && errno == EEXIST) fdsem_rd = semget(IPC_PRIVATE, 1, IPC_EXCL|S_IRUSR|S_IWUSR); if (fdsem_rd == -1) FAIL(MM_ERR_CORE|MM_ERR_SYSTEM, "failed to acquire semaphore"); mm_core_semctlarg.val = 0; semctl(fdsem_rd, 0, SETVAL, mm_core_semctlarg); #endif /* MM_SEMT_IPCSEM */ /* * Configure the memory core parameters */ mc = (mem_core *)area; mc->mc_size = size; mc->mc_usize = usersize; mc->mc_pid = getpid(); #if defined(MM_SHMT_IPCSHM) mc->mc_fdmem = fdmem; #endif #if defined(MM_SEMT_FLOCK) mc->mc_fdsem[0].pid = getpid(); mc->mc_fdsem[0].fd = fdsem; mc->mc_fdsem[1].pid = 0; mc->mc_fdsem[1].fd = -1; #else mc->mc_fdsem = fdsem; #endif #if defined(MM_SEMT_BEOS) mc->mc_semid = create_sem(0, "mm_semid"); mc->mc_ben = 0; #endif #if defined(MM_SHMT_BEOS) mc->mc_areaid = temparea; #endif #if defined(MM_SEMT_IPCSEM) mc->mc_fdsem_rd = fdsem_rd; mc->mc_readers = 0; #endif #if defined(MM_SHMT_MMFILE) memcpy(mc->mc_fnmem, fnmem, MM_MAXPATH); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) memcpy(mc->mc_fnsem, fnsem, MM_MAXPATH); #endif /* * Return successfully established core */ return ((void *)&(mc->mc_base.mw_cp)); /* * clean-up sequence (CUS) for error situation */ BEGIN_FAILURE #if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMFILE) if (area != ((void *)-1)) munmap((caddr_t)area, size); #endif #if defined(MM_SHMT_IPCSHM) if (area != ((void *)-1)) shmdt(area); #endif #if defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE) if (fdmem != -1) close(fdmem); #endif #if defined(MM_SEMT_BEOS) delete_sem(mc->mc_semid); #endif #if defined(MM_SHMT_BEOS) delete_area(mc->mc_areaid); #endif #if defined(MM_SHMT_IPCSHM) if (fdmem != -1) shmctl(fdmem, IPC_RMID, NULL); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) if (fdsem != -1) close(fdsem); #endif #if defined(MM_SEMT_IPCSEM) if (fdsem != -1) semctl(fdsem, 0, IPC_RMID, 0); if (fdsem_rd != -1) semctl(fdsem_rd, 0, IPC_RMID, 0); #endif #if defined(MM_SHMT_MMFILE) unlink(fnmem); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) unlink(fnsem); #endif return NULL; END_FAILURE }
int main (int argc, char* argv[]) { key_t klucz = ftok("./../..",'L'); if(klucz == -1) { fprintf(stderr,"KONSUMENT: Blad tworzenia klucza dla zbioru semaforów!\n"); exit(3); } else fprintf(stdout,"KONSUMENT: Wartosc wygenerowanego klucza dla zbioru semaforow: %ld\n", klucz); // przyłączanie zbioru semaforów: int ilosc_sem = 4; int id_semafor = semget(klucz, ilosc_sem, IPC_CREAT|0600); if (id_semafor == -1) { fprintf(stderr,"KONSUMENT: Blad przyłączania zbioru semaforow!\n"); exit(EXIT_FAILURE); } else fprintf(stdout,"KONSUMENT: Zbior semaforow przyłączony, id= %d\n", id_semafor); FILE* wyjscie = fopen("out.txt", "w"); if(wyjscie == 0) { fprintf(stderr,"KONSUMENT: Blad otwierania pliku wyjsciowego!\n"); exit(EXIT_FAILURE); } else fprintf(stdout, "KONSUMENT: Plik wyjsciowy otwarty!\n"); // przylaczenie segmentu pamięci dzielonej int id_pamiec = shmget(klucz, 4, IPC_CREAT|0600); if (id_pamiec == -1) { fprintf(stderr, "KONSUMENT: Blad przylaczenia segmentu pamieci dzielonej!\n"); exit(EXIT_FAILURE); } else fprintf(stdout, "KONSUMENT: Pomyslnie przylaczono segment pamieci dzielonej o ID: %d\n", id_pamiec); //uzyskanie adresu segmentu pamieci dzielonej char* adres=(char*)shmat(id_pamiec, 0, 0); if (*adres==-1) { fprintf(stderr, "KONSUMENT: Blad uzyskania dostepu do segmentu pamieci dzielonej!\n"); exit(EXIT_FAILURE); } else fprintf(stdout, "KONSUMENT: Pomyslnie uzyskano dostep do segmentu pamieci dzielonej: %X\n", adres); char znak; int status; while(1) { opusc_semafor(id_semafor, 0); if(semctl(id_semafor, 2, GETVAL, NULL) <= 0) break; znak=*adres; srand(time(NULL)); //usleep(rand() % 100); fputc(znak, wyjscie); if(ferror(wyjscie)) fprintf(stderr, "PRODUCENT: Blad zapisu znaku do pliku wejsciowego!\n"); podnies_semafor(id_semafor, 1); } if(status < 0) { fprintf(stderr,"KONSUMENT: Blad pobierania wartosci semafora nr 2\n"); exit(EXIT_FAILURE); } fprintf(stdout,"KONSUMENT: zakonczono kopiowanie znakow\n"); podnies_semafor(id_semafor, 3); //zamkniecie pliku if(fclose(wyjscie) == EOF) { fprintf(stderr,"PRODUCENT: Blad zamykania pliku wyjsciowego\n"); exit(EXIT_FAILURE); } else fprintf(stdout, "KONSUMENT: Pomyslnie zamknieto plik wyjsciowy\n"); return 0; }
ce_int_t ce_sem_create(ce_sem_t *sem, unsigned int semnum) { int sem_id; key_t sem_key; union semun arg; struct sembuf initop; int save_errno; int cnt = 0; /*get key*/ sem_key=ftok((const char*)sem->name.data,sem->proj_id); if(-1 == sem_key) { return CE_ERROR; } sem_id=semget(sem_key, semnum, IPC_CREAT|IPC_EXCL|0666); if(sem_id != -1) { for (cnt = 0; cnt < semnum; cnt++) { /*init sem*/ arg.val=0; if(semctl(sem_id,cnt,SETVAL,arg)<0) { goto err; } initop.sem_num=cnt; initop.sem_op=sem->sem_val<=0?1:sem->sem_val; initop.sem_flg=0; if(semop(sem_id,&initop,1)<0) { goto err; } } goto fin; } else if(errno!=EEXIST) { goto err; } else //sem existed,then open it { sem_id=semget(sem_key,0,0); goto fin; } err: save_errno=errno; if(sem_id!=-1) { semctl(sem_id,0,IPC_RMID); } errno=save_errno; return CE_ERROR; fin: sem->sem_id=sem_id; return CE_OK; }
/* Open or create a semaphore initializing it as necessary. */ static int semid_get(const char *name, int nsems, int oflags, mode_t mode, int value) { key_t key; int max; if (nsems > MAX_SEMNUM) { ERR(errno = ERANGE, "semid_get"); return -1; } if ((key = ftok((char *)name, 1)) == (key_t)-1) { ERR(errno, "ftok"); return -1; } /* This following loop ensures that we know if the semaphore was created * as opposed to just opened so that it can be initialized properly. We * do this by alternating between oflags 0 and IPC_CREATE|IPC_EXCL until * one succeeds. */ for (max = MAX_TRIES; max; max--) { int semid; union semun arg; if ((oflags & O_EXCL) == 0) { if ((semid = semget(key, nsems, 0)) != -1) { struct semid_ds buf; /* This inner try-loop ensures that the semaphore is initialized before * we return even if the semaphore has been created with semget but not * yet initialized with semctl. See Stevens' UNPv2 p274. */ arg.buf = &buf; for (max = MAX_TRIES; max; max--) { if (semctl(semid, 0, IPC_STAT, arg) == -1) { ERR(errno, "semctl"); return -1; } if (buf.sem_otime != 0) { return semid; } sleep(1); } ERR(errno = ETIMEDOUT, "semid_get"); return -1; } else if (errno != ENOENT) { ERR(errno, "semget"); return -1; } } if ((semid = semget(key, nsems, IPC_CREAT | IPC_EXCL | (mode & 0777))) != -1) { struct sembuf initop; if (nsems > 1) { unsigned short array[MAX_SEMNUM * sizeof(unsigned short)]; int i; arg.array = array; arg.array[0] = 0; /* leave the first one 0 to be set with semop */ for (i = 1; i < nsems; i++) { arg.array[i] = value; } if (semctl(semid, 0, SETALL, arg) == -1) { ERR(errno, "semctl"); semctl(semid, 0, IPC_RMID); return -1; } } else { arg.val = 0; if (semctl(semid, 0, SETVAL, arg) == -1) { ERR(errno, "semctl"); semctl(semid, 0, IPC_RMID); return -1; } } /* increment by value to set sem_otime nonzero */ initop.sem_num = 0; initop.sem_op = value; initop.sem_flg = 0; if (semop(semid, &initop, 1) == -1) { ERR(errno, "semop"); semctl(semid, 0, IPC_RMID); return -1; } return semid; } else if ((oflags & O_EXCL) || errno != EEXIST) { ERR(errno, "semget"); return -1; } } ERR(errno = ETIMEDOUT, "semid_get"); return -1; }
/** * Returns a data-structure for accessing a shared-memory FIFO. Creates the * FIFO is it doesn't already exist. * * @retval !NULL Pointer the data-structure for accessing the * shared-memory FIFO. * @retval NULL Failure. An error message is logged. */ ShmHandle* shmfifo_create( const int npages, /**< size of the FIFO in pages */ const int privsz, /**< <size of the private portion of the FIFO in bytes */ const int nkey) /**< Partial key associated with the FIFO or \c -1 to obtain a private, shared-memory FIFO. */ { int shmSize = npages*getpagesize(); int shmid; struct shmhandle* shm = NULL; /* default failure */ key_t key; if (nkey == -1) { shmid = shmget(IPC_PRIVATE, shmSize, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); } else { key = (key_t)(DVBS_ID + nkey); /* * IPC_EXCL creates an error condition if the memory already exists... * we can use the existing memory if the program has not changed the * size of the segment or the private structure size */ shmid = shmget(key, shmSize, IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); } if (shmid == -1) { log_syserr("shmget() failure: npages=%d, nkey=%d", npages, nkey); } else { /* Temporarily attach to initialize the control structure. */ struct shmprefix* p = (struct shmprefix*)shmat(shmid, 0, 0); if (p == (void*)-1) { log_syserr("shmat() failure: id=%d", shmid); } else { int semid; p->read = p->write = sizeof(struct shmprefix) + privsz; p->sz = shmSize; p->privsz = privsz; (void)memset((char*)p + sizeof(struct shmprefix), 0, privsz); (void)shmdt(p); p = NULL; /* Get semaphore */ if (nkey == -1) { semid = semget(IPC_PRIVATE, SI_SEM_COUNT, (IPC_CREAT | IPC_EXCL) + 0600); } else { /* * IPC_EXCL not used in order to get existing semaphore if * possible. */ semid = semget(key, SI_SEM_COUNT, IPC_CREAT + 0660); } if (semid == -1) { log_syserr("semget() failure"); } else { unsigned short values[SI_SEM_COUNT]; union semun arg; log_debug("shmfifo_create(): Got semaphore: pid=%d, semid=%d", getpid(), semid); values[SI_LOCK] = 1; values[SI_WRITER] = 0; values[SI_READER] = 0; arg.array = values; if (semctl(semid, 0, SETALL, arg) == -1) { log_syserr("semctl() failure: semid=%d", semid); } else { shm = shmfifo_new(); if (NULL != shm) { shm->sid = shmid; shm->privsz = privsz; shm->sz = shmSize; shm->semid = semid; } } /* semaphore values set */ } /* got semaphore set */ } /* shared-memory was attached to "p" */ } /* got shared-memory segment ID */ return shm; }
~Semid1() { if (semctl(semid,0,IPC_RMID)==-1)throw_nynn_exception(errno,NULL); }
/*! \internal Setup unix_key */ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) { if (key.isEmpty()){ errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:")); error = QSystemSemaphore::KeyError; return -1; } // ftok requires that an actual file exists somewhere if (-1 != unix_key) return unix_key; // Create the file needed for ftok int built = QSharedMemoryPrivate::createUnixKeyFile(fileName); if (-1 == built) { errorString = QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:")); error = QSystemSemaphore::KeyError; return -1; } createdFile = (1 == built); // Get the unix key for the created file unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q'); if (-1 == unix_key) { errorString = QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:")); error = QSystemSemaphore::KeyError; return -1; } // Get semaphore semaphore = semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL); if (-1 == semaphore) { if (errno == EEXIST) semaphore = semget(unix_key, 1, 0666 | IPC_CREAT); if (-1 == semaphore) { setErrorString(QLatin1String("QSystemSemaphore::handle")); cleanHandle(); return -1; } } else { createdSemaphore = true; // Force cleanup of file, it is possible that it can be left over from a crash createdFile = true; } if (mode == QSystemSemaphore::Create) { createdSemaphore = true; createdFile = true; } // Created semaphore so initialize its value. if (createdSemaphore && initialValue >= 0) { qt_semun init_op; init_op.val = initialValue; if (-1 == semctl(semaphore, 0, SETVAL, init_op)) { setErrorString(QLatin1String("QSystemSemaphore::handle")); cleanHandle(); return -1; } } return unix_key; }
main() { struct sembuf P,V; union semun arg; int arrayid; int getid; int *array; int *get; int sumID; int *sum; sumID=shmget(IPC_PRIVATE,sizeof(int),IPC_CREAT|0666); sum=(int *)shmat(sumID,0,0); arrayid=shmget(IPC_PRIVATE,sizeof(int)*MAXSHM,IPC_CREAT|0666); getid=shmget(IPC_PRIVATE,sizeof(int),IPC_CREAT|0666); array=(int *)shmat(arrayid,0,0); get=(int *)shmat(getid,0,0); *get=0; fullid=semget(IPC_PRIVATE,1,IPC_CREAT|0666); emptyid=semget(IPC_PRIVATE,1,IPC_CREAT|0666); mutexid=semget(IPC_PRIVATE,1,IPC_CREAT|0666); arg.val=0; if(semctl(fullid,0,SETVAL,arg)==-1) perror("semctl setval error"); arg.val=MAXSHM; if(semctl(emptyid,0,SETVAL,arg)==-1) perror("semctl setval error"); arg.val=1; if(semctl(mutexid,0,SETVAL,arg)==-1) perror("semctl setval error"); P.sem_num=0; P.sem_op=-1; P.sem_flg=SEM_UNDO; V.sem_num=0; V.sem_op=1; V.sem_flg=SEM_UNDO; if(fork()==0) { int i=0; int set=0; while(i<10) { semop(emptyid,&P,1); semop(mutexid,&P,1); array[set%MAXSHM]=i+1; printf("Productor put number: %d\n",array[set%MAXSHM]); set++; semop(mutexid,&V,1); semop(fullid,&V,1); i++; } sleep(3); printf("Productor is over\n"); exit(0); } else { if(fork()==0) { while(1) { if(*get == 10) break; semop(fullid,&P,1); semop(mutexid,&P,1); printf("The ComsumerA get number: %d\n",array[(*get)%MAXSHM]); *sum+=array[(*get)%MAXSHM]; (*get)++; semop(mutexid,&V,1); semop(emptyid,&V,1); sleep(1); } printf("ComsumerA is over\n"); exit(0); } else { if(fork()==0) { while(1) { if(*get ==10) break; semop(fullid,&P,1); semop(mutexid,&P,1); printf("The ComsumerB get number: %d\n",array[(*get)%MAXSHM]); *sum+=array[(*get)%MAXSHM]; (*get)++; semop(mutexid,&V,1); semop(emptyid,&V,1); sleep(1); } printf("ComsumerB is over\n"); exit(0); } } } wait(0); wait(0); wait(0); shmdt(array); shmctl(arrayid,IPC_RMID,0); shmdt(get); shmctl(getid,IPC_RMID,0); semctl(emptyid,IPC_RMID,0); semctl(fullid,IPC_RMID,0); semctl(mutexid,IPC_RMID,0); printf("sum : %d\n",*sum); exit(0); }
/** * Get the status of semaphore * * @param semid semaphore identifier * @param semno semaphore number * * @return true for the flag on, false for the flag off */ bool qsem_check(int semid, int semno) { if (semctl(semid, semno, GETVAL, 0) == 0) return true; // locked return false; // unlocked }
int main(int argc, char *argv[]) { //定义共享缓冲区及其信号灯 int readbuf_id = shmget(IPC_PRIVATE, CACHE_LENGTH + sizeof(unsigned), IPC_CREAT | IPC_EXCL | 0666); int rbuf_empty = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0666); int rbuf_max = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0666); int writebuf_id = shmget(IPC_PRIVATE, CACHE_LENGTH + sizeof(unsigned), IPC_CREAT | IPC_EXCL | 0666); int wbuf_empty = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0666); int wbuf_max = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0666); int finish_id = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0666); int get_id = 0; int put_id = 0; int copy_id = 0; union semun semopts; FILE *out; FILE *in; int n; //打开源和目标文件 if (argc != 3) { puts("arguments error"); return 0; } if ((in = fopen(argv[1], "rb")) == NULL) { puts("can't open input file"); return 0; } if ((out = fopen(argv[2], "wb")) == NULL) { puts("can't open output file"); fclose(in); return 0; } //信号灯赋值 semopts.val = 1; semctl(rbuf_empty, 0, SETVAL, semopts); semctl(wbuf_empty, 0, SETVAL, semopts); semopts.val = 0; semctl(rbuf_max, 0, SETVAL, semopts); semctl(wbuf_max, 0, SETVAL, semopts); semctl(finish_id, 0, SETVAL, semopts); /*semctl(part_over, 0, SETVAL, semopts);*/ /*semctl(over, 0, SETVAL, semopts);*/ // get if ((get_id = fork()) == 0) { unsigned char *s = shmat(readbuf_id, 0, 0); puts("get:start to get"); do { P(rbuf_empty, 0); //加入copy n = fread(s + sizeof(unsigned), 1, CACHE_LENGTH, in); /*n = fread(s + sizeof(unsigned), 1, 2, in);*/ printf("read: %d\n", n); /*putchar('\n');*/ *(unsigned *)s = n; /*fwrite(s + sizeof(unsigned), 1, *(unsigned *)s, stdout);*/ V(rbuf_max, 0); if (*(unsigned *)s == 0) break; } while (1); fclose(in); /*sleep(5);*/ P(finish_id, 0); shmdt(s); //请加入保证三个进程同步结束的机制 puts("get: get ended"); return 0; } // copy if ((copy_id = fork()) == 0) { unsigned char *s1 = shmat(readbuf_id, 0, 0); unsigned char *s2 = shmat(writebuf_id, 0, 0); char buf[CACHE_LENGTH + sizeof(unsigned)]; puts("copy: start to copy"); do { P(rbuf_max, 0); //加入内容 n = *(unsigned *)s1; printf("copy: %d\n", n); memcpy(buf, s1, CACHE_LENGTH + sizeof(unsigned)); /*fwrite(s1 + sizeof(unsigned), 1, *(unsigned*)s1, stdout);*/ V(rbuf_empty, 0); P(wbuf_empty, 0); //加入内容 /**(unsigned *)s2 = n;*/ memcpy(s2, buf, CACHE_LENGTH + sizeof(unsigned)); printf("\ncopy: \n"); /*fwrite(s2 + sizeof(unsigned), 1, *(unsigned*)s2, stdout);*/ printf("\n\n"); V(wbuf_max, 0); if (*(unsigned *)s2 == 0) break; } while (1); P(finish_id, 0); shmdt(s1); shmdt(s2); //请加入保证三个进程同步结束的机制 puts("copy: copy ended"); /*sleep(5);*/ return 0; } // put if ((put_id = fork()) == 0) { unsigned char *s = shmat(writebuf_id, 0, 0); puts("put: start to put"); char buf_put[CACHE_LENGTH + sizeof(unsigned)]; do { P(wbuf_max, 0); //加入内容 /*memcpy(buf_put, s, CACHE_LENGTH + sizeof(unsigned));*/ printf("put: %d\n", *(unsigned *)s); /*if (*(unsigned*)s > 0)*/ /*{*/ fwrite(s + sizeof(unsigned), 1, *(unsigned *)s, out); fwrite(s + sizeof(unsigned), 1, *(unsigned *)s, stdout); /*}*/ fflush(out); V(wbuf_empty, 0); if (*(unsigned *)s == 0) { V(finish_id, 0); break; } } while (1); shmdt(s); fclose(out); //请加入保证三个进程同步结束的机制 puts("put: put ended"); return 0; } //请加入保证三个进程同步结束的机制 //请加入释放缓冲区和信号灯的机制 /*int status;*/ P(finish_id, 0); shmctl(readbuf_id, IPC_RMID, 0); shmctl(writebuf_id, IPC_RMID, 0); return 0; }
void uv_sem_destroy(uv_sem_t* sem) { if (-1 == semctl(*sem, 0, IPC_RMID)) abort(); }
int main (int argc, char ** argv) { int semid; key = rand(); #ifndef DO_BENCH printf("Semaphore key: 0x%8x\n", key); #endif /* server run first and client run later */ if (argc == 2 && strcmp(argv[1], "serial") == 0) { mode = SERIAL; if (fork() == 0) server(); wait(NULL); if (fork() == 0) client(); wait(NULL); } if ((semid = semget(key, 2, 0600|IPC_CREAT)) < 0) { perror("semget"); exit(1); } /* server run first and client run later (in the same process) */ if (argc == 2 && strcmp(argv[1], "in-process") == 0) { mode = IN_PROCESS; server(); client(); semctl(semid, 0, IPC_RMID); return 0; } pipe(pipefds); /* server to be the parent and client to be the child */ if (argc == 1) { if (fork() == 0) client(); else server(); } /* client to be the parent and server to be the child */ if (argc == 2 && strcmp(argv[1], "reverse") == 0) { if (fork() == 0) server(); else client(); } /* both client and server are children */ if (argc == 2 && strcmp(argv[1], "children") == 0) { if (fork() == 0) server(); if (fork() == 0) client(); wait(NULL); wait(NULL); } semctl(semid, 0, IPC_RMID); return 0; }
/*---------------------------------------------------------------------+ | main | | ==================================================================== | | | | Function: Main program (see prolog for more details) | | | | Returns: (0) Successful completion | | (-1) Error occurred | | | +---------------------------------------------------------------------*/ int main(int argc, char **argv) { uid_t uid = getuid(); /* User's user id */ gid_t gid = getgid(); /* User's group id */ int semid; /* Unique semaphore id */ int nsems = NUM_SEMAPHORES; /* Number of semaphores to create */ struct semid_ds exp_semdata; /* Expected semaphore values */ union semun exp_semdatap; struct semid_ds act_semdata; /* Actual semaphore values */ union semun act_semdatap; exp_semdatap.buf = &exp_semdata; act_semdatap.buf = &act_semdata; umask(0000); /* SET semid_ds STRUCTURE TO DESIRED VALUES........ */ /* * Initialize the "expected" sempahore value structure */ exp_semdata.sem_perm.cuid = exp_semdata.sem_perm.uid = uid; exp_semdata.sem_perm.cgid = exp_semdata.sem_perm.gid = gid; exp_semdata.sem_perm.mode = 0660; exp_semdata.sem_nsems = nsems; /* * Create a semaphore, set the semaphore fields and then * retrieve the fields. */ if ((semid = semget(IPC_PRIVATE, nsems, IPC_CREAT | 0666)) < 0) sys_error("semget (IPC_PRIVATE) failed", __LINE__); if (semctl(semid, nsems, IPC_SET, exp_semdatap) < 0) sys_error("semctl (IPC_SET) failed", __LINE__); if (semctl(semid, nsems, IPC_STAT, act_semdatap) < 0) sys_error("semctl (IPC_STAT) failed", __LINE__); /* * Verify that the semaphore fields were set correctly */ if (act_semdata.sem_perm.cuid != exp_semdata.sem_perm.cuid) error("sem_perm.cuid field was not set!", __LINE__); if (act_semdata.sem_perm.uid != exp_semdata.sem_perm.uid) error("sem_perm.uid field was not set!", __LINE__); if (act_semdata.sem_perm.cgid != exp_semdata.sem_perm.cgid) error("sem_perm.cgid field was not set!", __LINE__); if (act_semdata.sem_perm.gid != exp_semdata.sem_perm.gid) error("sem_perm.gid field was not set!", __LINE__); if (act_semdata.sem_perm.mode != exp_semdata.sem_perm.mode) error("sem_perm.mode field was not set!", __LINE__); if (act_semdata.sem_nsems != exp_semdata.sem_nsems) error("sem_nsems field was not set!", __LINE__); /* * Print out the id of the newly created semaphore for comparison * with the 'ipcs -s' command and then exit. */ printf("%d\n", semid); return (0); }
/* Return non-zero if successful; return zero on failure (no lock acquired). * If "wait" passed greater than zero do not attempt to assassinate a contender * (try to identify and print its PID anyways). Otherwise, having killed * the contender, try to re-acquire the lock (without. */ static int/*bool*/ s_Shmem_WLock(int which, int/*bool*/ wait) { static union semun dummy; int locked; int pid; #ifdef LBSM_DEBUG CORE_LOGF(eLOG_Trace, ("LBSM W-lock[%d] acquire%s", which + 1, wait ? " w/wait" : "")); #endif /*LBSM_DEBUG*/ if ((locked = s_Shmem_TryWLock(which)) == 0) return 1/*success*/; if (locked < 0) { /* even [1] was not successfully locked, so we have either * a/ a hanging writer, or * b/ a hanging old reader (which doesn't change [2] in block 0 only) * In either case, we can try to obtain a PID of the offender. */ if ((pid = semctl(s_Muxid, (which << 1) | 1, GETPID, dummy)) > 0) { int self = (pid_t) pid == getpid(); int other = !self && (kill(pid, 0) == 0 || errno == EPERM); int killed = 0; if (!wait) { if (other && kill(pid, SIGTERM) == 0) { CORE_LOGF_X(17, eLOG_Warning, ("Terminating PID %lu", (long) pid)); sleep(1); /* let them catch SIGTERM and exit gracefully */ kill(pid, SIGKILL); killed = 1; } else { CORE_LOGF_X(18, eLOG_Warning, ("Unable to kill PID %lu", (long) pid)); } } CORE_LOGF_X(19, eLOG_Warning, ("LBSM lock[%d] %s revoked from PID %lu (%s)", which + 1, killed ? "is being" : "has to be", (long) pid, self ? "self" : other ? (killed ? "killed" : "hanging") : "zombie")); } else if (pid < 0) return 0/*severe failure: most likely removed IPC id*/; } else { pid = 0; /* [1] was free (now locked) but [2] was taken by someone else, * we have a hanging reader, no additional info is available. */ if (!wait) { union semun arg; arg.val = 1; if (semctl(s_Muxid, (which << 1) + 2, SETVAL, arg) < 0) { CORE_LOGF_ERRNO_X(9, eLOG_Error, errno, ("Unable to adjust LBSM access count[%d]", which + 1)); } wait = 1/*this makes us undo [1] and fail*/; } if (wait) { int x_errno = errno; s_Shmem_Unlock(which, 1); errno = x_errno; } } if (!pid) { int val; if ((val = semctl(s_Muxid, (which << 1) + 2, GETVAL, dummy)) > 1) { CORE_LOGF_X(20, eLOG_Warning, ("%u hanging readers in LBSM shmem[%d]%s", (unsigned int) val, which + 1, wait ? "" : locked < 0 ? ", revoking lock" : ", lock revoked")); } else { CORE_LOGF_X(21, eLOG_Warning, ("A hanging reader in LBSM shmem[%d]%s", which + 1, wait ? "" : locked < 0 ? ", revoking lock" : ", lock revoked")); } } if (wait) return 0/*failure*/; if (locked > 0) return 1/*success: good to go*/; #ifdef LBSM_DEBUG CORE_LOGF(eLOG_Trace, ("LBSM W-lock[%d] re-acquire", which + 1)); #endif /*LBSM_DEBUG*/ return s_Shmem_WLock(which, 0/*no wait*/); }
void ctrlc_handler(int sig) { union semun dummy; semctl(semid, 0, IPC_RMID, dummy); shmctl(shmid, IPC_RMID, NULL); }
void semSet() { semunion.val = count; semctl(semid, 0, SETVAL , semunion); }
static int swSem_free(swLock *lock) { return semctl(lock->object.sem.semid, 0, IPC_RMID); }
/** * int ipc_comm_cleanup() * @brief Cleans up the IPC structure * @param ipc structure pointer * @return EXIT_FAILURE for unknown type, EXIT_SUCCESS for known/success */ int ipc_comm_cleanup(ipc_comm_t* ipc_comm){ free(ipc_comm->sops); semctl(ipc_comm->semid, INTERFACE_CONNECTED, IPC_RMID, 0); return EXIT_SUCCESS; }
int main(void) { static const key_t private_key = (key_t) (0xffffffff00000000ULL | IPC_PRIVATE); static const key_t bogus_key = (key_t) 0xeca86420fdb97531ULL; static const int bogus_semid = 0xfdb97531; static const int bogus_semnum = 0xeca86420; static const int bogus_size = 0xdec0ded1; static const int bogus_flags = 0xface1e55; static const int bogus_cmd = 0xdeadbeef; static const unsigned long bogus_arg = (unsigned long) 0xbadc0dedfffffaceULL; int rc; union semun un; struct semid_ds ds; struct seminfo info; rc = semget(bogus_key, bogus_size, bogus_flags); printf("semget\\(%#llx, %d, %s%s%s%#x\\|%#04o\\) += %s\n", zero_extend_signed_to_ull(bogus_key), bogus_size, IPC_CREAT & bogus_flags ? "IPC_CREAT\\|" : "", IPC_EXCL & bogus_flags ? "IPC_EXCL\\|" : "", IPC_NOWAIT & bogus_flags ? "IPC_NOWAIT\\|" : "", bogus_flags & ~(0777 | IPC_CREAT | IPC_EXCL | IPC_NOWAIT), bogus_flags & 0777, sprintrc_grep(rc)); id = semget(private_key, 1, 0600); if (id < 0) perror_msg_and_skip("semget"); printf("semget\\(IPC_PRIVATE, 1, 0600\\) += %d\n", id); atexit(cleanup); rc = semctl(bogus_semid, bogus_semnum, bogus_cmd, bogus_arg); #ifdef __GLIBC__ # define SEMCTL_BOGUS_ARG_FMT "(%#lx|\\[(%#lx|NULL)\\])" #else # define SEMCTL_BOGUS_ARG_FMT "(%#lx|\\[(%#lx|NULL)\\]|NULL)" #endif printf("semctl\\(%d, %d, (IPC_64\\|)?%#x /\\* SEM_\\?\\?\\? \\*/" ", " SEMCTL_BOGUS_ARG_FMT "\\) += %s\n", bogus_semid, bogus_semnum, bogus_cmd, bogus_arg, bogus_arg, sprintrc_grep(rc)); un.buf = &ds; if (semctl(id, 0, IPC_STAT, un)) perror_msg_and_skip("semctl IPC_STAT"); printf("semctl\\(%d, 0, (IPC_64\\|)?IPC_STAT, \\[?%p\\]?\\) += 0\n", id, &ds); un.__buf = &info; rc = semctl(0, 0, SEM_INFO, un); printf("semctl\\(0, 0, (IPC_64\\|)?SEM_INFO, \\[?%p\\]?\\) += %s\n", &info, sprintrc_grep(rc)); un.buf = &ds; rc = semctl(id, 0, SEM_STAT, un); printf("semctl\\(%d, 0, (IPC_64\\|)?SEM_STAT, \\[?%p\\]?\\) += %s\n", id, &ds, sprintrc_grep(rc)); return 0; }
/* Deallocate a binary semaphore. All users must have finished their use. Returns -1 on failure. */ int binary_semaphore_deallocate(int semid) { union semun ignored_argument; return semctl(semid, 1, IPC_RMID, ignored_argument); }
void gds_rundown(void) { bool is_mm, we_are_last_user, we_are_last_writer; boolean_t ipc_deleted, remove_shm, cancelled_timer, cancelled_dbsync_timer, vermismatch; now_t now; /* for GET_CUR_TIME macro */ char *time_ptr, time_str[CTIME_BEFORE_NL + 2]; /* for GET_CUR_TIME macro */ gd_region *reg; int save_errno, status; int4 semval, ftok_semval, sopcnt, ftok_sopcnt; short crash_count; sm_long_t munmap_len; sgmnt_addrs *csa; sgmnt_data_ptr_t csd; struct shmid_ds shm_buf; struct sembuf sop[2], ftok_sop[2]; uint4 jnl_status; unix_db_info *udi; jnl_private_control *jpc; jnl_buffer_ptr_t jbp; error_def(ERR_CRITSEMFAIL); error_def(ERR_DBCCERR); error_def(ERR_DBFILERR); error_def(ERR_DBRNDWNWRN); error_def(ERR_ERRCALL); error_def(ERR_GBLOFLOW); error_def(ERR_GTMASSERT); error_def(ERR_IPCNOTDEL); error_def(ERR_JNLFLUSH); error_def(ERR_RNDWNSEMFAIL); error_def(ERR_TEXT); error_def(ERR_WCBLOCKED); forced_exit = FALSE; /* Okay, we're dying already -- let rel_crit live in peace now. * If coming through a DAL, not necessarily dying. what to do then? -- nars -- 8/15/2001 */ grabbed_access_sem = FALSE; jnl_status = 0; reg = gv_cur_region; /* Local copy */ /* * early out for cluster regions * to avoid tripping the assert below. * Note: * This early out is consistent with VMS. It has been * noted that all of the gtcm assignments * to gv_cur_region should use the TP_CHANGE_REG * macro. This would also avoid the assert problem * and should be done eventually. */ if (dba_cm == reg->dyn.addr->acc_meth) return; udi = FILE_INFO(reg); csa = &udi->s_addrs; csd = csa->hdr; assert(csa == cs_addrs && csd == cs_data); if ((reg->open) && (dba_usr == csd->acc_meth)) { change_reg(); gvusr_rundown(); return; } ESTABLISH(gds_rundown_ch); if (!reg->open) /* Not open, no point to rundown */ { if (reg->opening) /* Died partway open, kill rest of way */ { rel_crit(reg); mutex_cleanup(reg); /* revist this to handle MM properly SMW 98/12/16 if (NULL != csa->nl) { status = shmdt((caddr_t)csa->nl); if (-1 == status) send_msg(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error during shmdt"), errno); } */ shmdt((caddr_t)csa->nl); csa->nl = NULL; } REVERT; return; } switch(csd->acc_meth) { /* Pass mm and bg through */ case dba_bg: is_mm = FALSE; break; case dba_mm: is_mm = TRUE; break; case dba_usr: assert(FALSE); default: REVERT; return; } /* Cancel any pending flush timer for this region by this task */ CANCEL_DB_TIMERS(reg, cancelled_timer, cancelled_dbsync_timer); we_are_last_user = FALSE; if (!csa->persistent_freeze) region_freeze(reg, FALSE, FALSE, FALSE); assert(!csa->read_lock); rel_crit(reg); /* get locks to known state */ mutex_cleanup(reg); /* * We need to guarantee that none else access database file header when semid/shmid fields are reset. * We already have created ftok semaphore in db_init or, mu_rndwn_file and did not remove it. * So just lock it. We do it in blocking mode. */ if (!ftok_sem_lock(reg, FALSE, FALSE)) rts_error(VARLSTCNT(4) ERR_DBFILERR, 2, DB_LEN_STR(reg)); /* * For mupip_jnl_recover we already have database access control semaphore. * We do not release it. We release it from mur_close_files. */ if (!mupip_jnl_recover) { sop[0].sem_num = 0; sop[0].sem_op = 0; /* Wait for 0 */ sop[1].sem_num = 0; sop[1].sem_op = 1; /* Lock */ sopcnt = 2; sop[0].sem_flg = sop[1].sem_flg = SEM_UNDO | IPC_NOWAIT; /* Don't wait the first time thru */ SEMOP(udi->semid, sop, sopcnt, status); if (-1 == status) /* We couldn't get it in one shot -- see if we already have it */ { save_errno = errno; /* see comment about Linux specific difference in behaviour of semctl() with GETPID in gds_rundown_ch() */ if (semctl(udi->semid, 0, GETPID) == process_id) { send_msg(VARLSTCNT(5) MAKE_MSG_INFO(ERR_CRITSEMFAIL), 2, DB_LEN_STR(reg), ERR_RNDWNSEMFAIL); REVERT; return; /* Already in rundown for this region */ } if (EAGAIN != save_errno) { assert(FALSE); rts_error(VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("gds_rundown first semop/semctl"), save_errno); } sop[0].sem_flg = sop[1].sem_flg = SEM_UNDO; /* Try again - blocking this time */ SEMOP(udi->semid, sop, 2, status); if (-1 == status) /* We couldn't get it at all.. */ rts_error(VARLSTCNT(5) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), errno); } } grabbed_access_sem = TRUE; /* * We now have the dbinit/rundown lock, so we are alone in this code for this region * and nobody else can attach. * See if we are all alone in accessing this database shared memory. */ assert(csa->ref_cnt); /* decrement private ref_cnt before shared ref_cnt decrement. */ csa->ref_cnt--; /* Currently journaling logic in gds_rundown() in VMS relies on this order to detect last writer */ assert(!csa->ref_cnt); --csa->nl->ref_cnt; if (memcmp(csa->nl->now_running, gtm_release_name, gtm_release_name_len + 1)) { /* VERMISMATCH condition. Possible only if DSE */ assert(dse_running); vermismatch = TRUE; } else vermismatch = FALSE; if (-1 == shmctl(udi->shmid, IPC_STAT, &shm_buf)) { save_errno = errno; rts_error(VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("gds_rundown shmctl"), save_errno); } else we_are_last_user = (1 == shm_buf.shm_nattch) && !vermismatch; assert(!mupip_jnl_recover || we_are_last_user); /* recover => one user */ if (-1 == (semval = semctl(udi->semid, 1, GETVAL))) rts_error(VARLSTCNT(5) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), errno); we_are_last_writer = (1 == semval) && (FALSE == reg->read_only) && !vermismatch;/* There's one writer left and I am it */ assert(!(mupip_jnl_recover && !reg->read_only) || we_are_last_writer); /* recover + R/W region => one writer */ if (-1 == (ftok_semval = semctl(udi->ftok_semid, 1, GETVAL))) rts_error(VARLSTCNT(5) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), errno); /* If csa->nl->donotflush_dbjnl is set, it means mupip recover/rollback was interrupted and therefore we should * not flush shared memory contents to disk as they might be in an inconsistent state. * In this case, we will go ahead and remove shared memory (without flushing the contents) in this routine. * A reissue of the recover/rollback command will restore the database to a consistent state. * Otherwise, if we have write access to this region, let us perform a few writing tasks. */ if (csa->nl->donotflush_dbjnl) csa->wbuf_dqd = 0; /* ignore csa->wbuf_dqd status as we do not care about the cache contents */ else if (!reg->read_only && !vermismatch) { /* If we had an orphaned block and were interrupted, set wc_blocked so we can invoke wcs_recover */ if (csa->wbuf_dqd) { grab_crit(reg); SET_TRACEABLE_VAR(csd->wc_blocked, TRUE); BG_TRACE_PRO_ANY(csa, wcb_gds_rundown); send_msg(VARLSTCNT(8) ERR_WCBLOCKED, 6, LEN_AND_LIT("wcb_gds_rundown"), process_id, &csa->ti->curr_tn, DB_LEN_STR(reg)); csa->wbuf_dqd = 0; wcs_recover(reg); if (is_mm) { assert(FALSE); csd = csa->hdr; } BG_TRACE_PRO_ANY(csa, lost_block_recovery); rel_crit(reg); } if (JNL_ENABLED(csd) && (GTCM_GNP_SERVER_IMAGE == image_type)) originator_prc_vec = NULL; /* If we are the last writing user, then everything must be flushed */ if (we_are_last_writer) { /* Time to flush out all of our buffers */ if (is_mm) { if (csa->total_blks != csa->ti->total_blks) /* do remap if file had been extended */ { grab_crit(reg); wcs_mm_recover(reg); csd = csa->hdr; rel_crit(reg); } csa->nl->remove_shm = TRUE; } /* Note WCSFLU_SYNC_EPOCH ensures the epoch is synced to the journal and indirectly * also ensures that the db is fsynced. We don't want to use it in the calls to * wcs_flu() from t_end() and tp_tend() since we can defer it to out-of-crit there. * In this case, since we are running down, we don't have any such option. */ csa->nl->remove_shm = wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SYNC_EPOCH); /* Since we_are_last_writer, we should be guaranteed that wcs_flu() did not change csd, (in * case of MM for potential file extension), even if it did a grab_crit(). Therefore, make * sure that's true. */ assert(csd == csa->hdr); assert(0 == memcmp(csd->label, GDS_LABEL, GDS_LABEL_SZ - 1)); csd->trans_hist.header_open_tn = csd->trans_hist.curr_tn; } else if ((cancelled_timer && (0 > csa->nl->wcs_timers)) || cancelled_dbsync_timer) { /* cancelled pending db or jnl flush timers - flush database and journal buffers to disk */ grab_crit(reg); /* we need to sync the epoch as the fact that there is no active pending flush timer implies * there will be noone else who will flush the dirty buffers and EPOCH to disk in a timely fashion */ wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SYNC_EPOCH); rel_crit(reg); assert((dba_mm == cs_data->acc_meth) || (csd == cs_data)); csd = cs_data; /* In case this is MM and wcs_flu() remapped an extended database, reset csd */ } /* Do rundown journal processing after buffer flushes since they require jnl to be open */ if (JNL_ENABLED(csd)) { /* the following tp_change_reg() is not needed due to the assert csa == cs_addrs at the beginning * of gds_rundown(), but just to be safe. To be removed by 2002!! --- nars -- 2001/04/25. */ tp_change_reg(); /* call this because jnl_ensure_open checks cs_addrs rather than gv_cur_region */ jpc = csa->jnl; jbp = jpc->jnl_buff; if (jbp->fsync_in_prog_latch.u.parts.latch_pid == process_id) { assert(FALSE); COMPSWAP_UNLOCK(&jbp->fsync_in_prog_latch, process_id, 0, LOCK_AVAILABLE, 0); } if (jbp->io_in_prog_latch.u.parts.latch_pid == process_id) { assert(FALSE); COMPSWAP_UNLOCK(&jbp->io_in_prog_latch, process_id, 0, LOCK_AVAILABLE, 0); } if (((NOJNL != jpc->channel) && !JNL_FILE_SWITCHED(jpc)) || we_are_last_writer && (0 != csa->nl->jnl_file.u.inode)) { /* We need to close the journal file cleanly if we have the latest generation journal file open * or if we are the last writer and the journal file is open in shared memory (not necessarily * by ourselves e.g. the only process that opened the journal got shot abnormally) * Note: we should not infer anything from the shared memory value of csa->nl->jnl_file.u.inode * if we are not the last writer as it can be concurrently updated. */ grab_crit(reg); if (JNL_ENABLED(csd)) { SET_GBL_JREC_TIME; /* jnl_ensure_open/jnl_put_jrt_pini/pfin/jnl_file_close all need it */ /* Before writing to jnlfile, adjust jgbl.gbl_jrec_time if needed to maintain time order * of jnl records. This needs to be done BEFORE the jnl_ensure_open as that could write * journal records (if it decides to switch to a new journal file). */ ADJUST_GBL_JREC_TIME(jgbl, jbp); jnl_status = jnl_ensure_open(); if (0 == jnl_status) { /* If we_are_last_writer, we would have already done a wcs_flu() which would * have written an epoch record and we are guaranteed no further updates * since we are the last writer. So, just close the journal. * Although we assert pini_addr should be non-zero for last_writer, we * play it safe in PRO and write a PINI record if not written already. */ assert(!jbp->before_images || is_mm || !we_are_last_writer || 0 != jpc->pini_addr); if (we_are_last_writer && 0 == jpc->pini_addr) jnl_put_jrt_pini(csa); if (0 != jpc->pini_addr) jnl_put_jrt_pfin(csa); /* If not the last writer and no pending flush timer left, do jnl flush now */ if (!we_are_last_writer && (0 > csa->nl->wcs_timers)) { if (SS_NORMAL == (jnl_status = jnl_flush(reg))) { assert(jbp->freeaddr == jbp->dskaddr); jnl_fsync(reg, jbp->dskaddr); assert(jbp->fsync_dskaddr == jbp->dskaddr); } else { send_msg(VARLSTCNT(9) ERR_JNLFLUSH, 2, JNL_LEN_STR(csd), ERR_TEXT, 2, RTS_ERROR_TEXT("Error with journal flush in gds_rundown"), jnl_status); assert(NOJNL == jpc->channel);/* jnl file lost has been triggered */ /* In this routine, all code that follows from here on does not * assume anything about the journaling characteristics of this * database so it is safe to continue execution even though * journaling got closed in the middle. */ } } jnl_file_close(reg, we_are_last_writer, FALSE); } else send_msg(VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(csd), DB_LEN_STR(reg)); } rel_crit(reg); } } if (we_are_last_writer) /* Flush the fileheader last and harden the file to disk */ { grab_crit(reg); /* To satisfy crit requirement in fileheader_sync() */ memset(csd->machine_name, 0, MAX_MCNAMELEN); /* clear the machine_name field */ if (!mupip_jnl_recover && we_are_last_user) { /* mupip_jnl_recover will do this after mur_close_file */ csd->semid = INVALID_SEMID; csd->shmid = INVALID_SHMID; csd->gt_sem_ctime.ctime = 0; csd->gt_shm_ctime.ctime = 0; } fileheader_sync(reg); rel_crit(reg); if (FALSE == is_mm) { if (-1 == fsync(udi->fd)) /* Sync it all */ { rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("Error during file sync at close"), errno); } } else { /* Now do final MM file sync before exit */ #if !defined(TARGETED_MSYNC) && !defined(NO_MSYNC) if (-1 == fsync(udi->fd)) /* Sync it all */ { rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("Error during file sync at close"), errno); } #else if (-1 == msync((caddr_t)csa->db_addrs[0], (size_t)(csa->db_addrs[1] - csa->db_addrs[0]), MS_SYNC)) { rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("Error during file msync at close"), errno); } #endif } } } /* end if (!reg->read_only && !csa->nl->donotflush_dbjnl) */ if (reg->read_only && we_are_last_user && !mupip_jnl_recover) { /* mupip_jnl_recover will do this after mur_close_file */ db_ipcs.semid = INVALID_SEMID; db_ipcs.shmid = INVALID_SHMID; db_ipcs.gt_sem_ctime = 0; db_ipcs.gt_shm_ctime = 0; db_ipcs.fn_len = reg->dyn.addr->fname_len; memcpy(db_ipcs.fn, reg->dyn.addr->fname, reg->dyn.addr->fname_len); db_ipcs.fn[reg->dyn.addr->fname_len] = 0; /* request gtmsecshr to flush. read_only cannot flush itself */ if (0 != send_mesg2gtmsecshr(FLUSH_DB_IPCS_INFO, 0, (char *)NULL, 0)) rts_error(VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("gtmsecshr failed to update database file header")); } /* Done with file now, close it */ if (-1 == close(udi->fd)) { rts_error(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error during file close"), errno); } /* Unmap storage if mm mode but only the part that is not the fileheader (so shows up in dumps) */ if (is_mm) { munmap_len = (sm_long_t)((csa->db_addrs[1] - csa->db_addrs[0]) - ROUND_UP(SIZEOF_FILE_HDR(csa->hdr), MSYNC_ADDR_INCS)); if (munmap_len > 0) { munmap((caddr_t)(csa->db_addrs[0] + ROUND_UP(SIZEOF_FILE_HDR(csa->hdr), MSYNC_ADDR_INCS)), (size_t)(munmap_len)); #ifdef DEBUG_DB64 rel_mmseg((caddr_t)csa->db_addrs[0]); #endif } } /* Detach our shared memory while still under lock so reference counts will be * correct for the next process to run down this region. * In the process also get the remove_shm status from node_local before detaching. * If csa->nl->donotflush_dbjnl is TRUE, it means we can safely remove shared memory without compromising data * integrity as a reissue of recover will restore the database to a consistent state. */ remove_shm = !vermismatch && (csa->nl->remove_shm || csa->nl->donotflush_dbjnl); status = shmdt((caddr_t)csa->nl); csa->nl = NULL; /* dereferencing nl after detach is not right, so we set it to NULL so that we can test before dereference*/ if (-1 == status) send_msg(VARLSTCNT(9) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, LEN_AND_LIT("Error during shmdt"), errno); reg->open = FALSE; /* If file is still not in good shape, die here and now before we get rid of our storage */ if (csa->wbuf_dqd) GTMASSERT; ipc_deleted = FALSE; /* If we are the very last user, remove shared storage id and the semaphores */ if (we_are_last_user) { /* remove shared storage, only if last writer to rundown did a successful wcs_flu() */ assert(!vermismatch); if (remove_shm) { ipc_deleted = TRUE; if (0 != shm_rmid(udi->shmid)) rts_error(VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("Unable to remove shared memory")); } else if (is_src_server || is_updproc) { gtm_putmsg(VARLSTCNT(6) ERR_DBRNDWNWRN, 4, DB_LEN_STR(reg), process_id, process_id); send_msg(VARLSTCNT(6) ERR_DBRNDWNWRN, 4, DB_LEN_STR(reg), process_id, process_id); } else send_msg(VARLSTCNT(6) ERR_DBRNDWNWRN, 4, DB_LEN_STR(reg), process_id, process_id); /* * Don't release semaphore in case of mupip recover/rollback; since it has standalone access. * It will release the semaphore in mur_close_files. */ if (!mupip_jnl_recover) { if (0 != sem_rmid(udi->semid)) rts_error(VARLSTCNT(8) ERR_DBFILERR, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("Unable to remove semaphore")); grabbed_access_sem = FALSE; } } else { assert(!mupip_jnl_recover); /* If we were writing, get rid of our writer access count semaphore */ if (!reg->read_only) if (0 != (save_errno = do_semop(udi->semid, 1, -1, SEM_UNDO))) rts_error(VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("gds_rundown write semaphore release"), save_errno); /* Now remove the rundown lock */ if (0 != (save_errno = do_semop(udi->semid, 0, -1, SEM_UNDO))) rts_error(VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(reg), ERR_TEXT, 2, RTS_ERROR_TEXT("gds_rundown rundown semaphore release"), save_errno); grabbed_access_sem = FALSE; } if (!ftok_sem_release(reg, !mupip_jnl_recover, FALSE)) rts_error(VARLSTCNT(4) ERR_DBFILERR, 2, DB_LEN_STR(reg)); if (!ipc_deleted) { GET_CUR_TIME; if (is_src_server) gtm_putmsg(VARLSTCNT(8) ERR_IPCNOTDEL, 6, CTIME_BEFORE_NL, time_ptr, LEN_AND_LIT("Source server"), REG_LEN_STR(reg)); if (is_updproc) gtm_putmsg(VARLSTCNT(8) ERR_IPCNOTDEL, 6, CTIME_BEFORE_NL, time_ptr, LEN_AND_LIT("Update process"), REG_LEN_STR(reg)); if (mupip_jnl_recover) { gtm_putmsg(VARLSTCNT(8) ERR_IPCNOTDEL, 6, CTIME_BEFORE_NL, time_ptr, LEN_AND_LIT("Mupip journal process"), REG_LEN_STR(reg)); send_msg(VARLSTCNT(8) ERR_IPCNOTDEL, 6, CTIME_BEFORE_NL, time_ptr, LEN_AND_LIT("Mupip journal process"), REG_LEN_STR(reg)); } } REVERT; }
/* 删除信号量 */ int sem_del(int semid) { union semun sun; return semctl (semid, 0, IPC_RMID, sun); }
void iniSEM(int semID,ushort queSemaforo, int queValor){ semctl(semID,queSemaforo,SETVAL,queValor); }
/* 初始化信号量函数*/ int init_sem (int semid, int sem_num, int val) { union semun sun; sun.val = val; return semctl (semid, sem_num, SETVAL, sun); }
CSem::~CSem() { if(-1 == semctl(m_SemId, 0, IPC_RMID)){ cerr << "error remove sem!" << endl; } }
/* * Create a semaphore set with the given number of useful semaphores * (an additional sema is actually allocated to serve as identifier). * Dead Postgres sema sets are recycled if found, but we do not fail * upon collision with non-Postgres sema sets. * * The idea here is to detect and re-use keys that may have been assigned * by a crashed postmaster or backend. */ static IpcSemaphoreId IpcSemaphoreCreate(int numSems) { IpcSemaphoreId semId; union semun semun; PGSemaphoreData mysema; /* Loop till we find a free IPC key */ for (nextSemaKey++;; nextSemaKey++) { pid_t creatorPID; /* Try to create new semaphore set */ semId = InternalIpcSemaphoreCreate(nextSemaKey, numSems + 1); if (semId >= 0) break; /* successful create */ /* See if it looks to be leftover from a dead Postgres process */ semId = semget(nextSemaKey, numSems + 1, 0); if (semId < 0) continue; /* failed: must be some other app's */ if (IpcSemaphoreGetValue(semId, numSems) != PGSemaMagic) continue; /* sema belongs to a non-Postgres app */ /* * If the creator PID is my own PID or does not belong to any extant * process, it's safe to zap it. */ creatorPID = IpcSemaphoreGetLastPID(semId, numSems); if (creatorPID <= 0) continue; /* oops, GETPID failed */ if (creatorPID != getpid()) { if (kill(creatorPID, 0) == 0 || errno != ESRCH) continue; /* sema belongs to a live process */ } /* * The sema set appears to be from a dead Postgres process, or from a * previous cycle of life in this same process. Zap it, if possible. * This probably shouldn't fail, but if it does, assume the sema set * belongs to someone else after all, and continue quietly. */ semun.val = 0; /* unused, but keep compiler quiet */ if (semctl(semId, 0, IPC_RMID, semun) < 0) continue; /* * Now try again to create the sema set. */ semId = InternalIpcSemaphoreCreate(nextSemaKey, numSems + 1); if (semId >= 0) break; /* successful create */ /* * Can only get here if some other process managed to create the same * sema key before we did. Let him have that one, loop around to try * next key. */ } /* * OK, we created a new sema set. Mark it as created by this process. We * do this by setting the spare semaphore to PGSemaMagic-1 and then * incrementing it with semop(). That leaves it with value PGSemaMagic * and sempid referencing this process. */ IpcSemaphoreInitialize(semId, numSems, PGSemaMagic - 1); mysema.semId = semId; mysema.semNum = numSems; PGSemaphoreUnlock(&mysema); return semId; }
void mm_core_delete(void *core) { mem_core *mc; #if defined(MM_SHMT_IPCSHM) int fdmem; #endif int fdsem; #if defined(MM_SEMT_IPCSEM) int fdsem_rd; #endif size_t size; #if defined(MM_SHMT_MMFILE) char fnmem[MM_MAXPATH]; #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) char fnsem[MM_MAXPATH]; #endif if (core == NULL) return; mc = (mem_core *)((char *)core-SIZEOF_mem_core); size = mc->mc_size; #if defined(MM_SHMT_IPCSHM) fdmem = mc->mc_fdmem; #endif #if !defined(MM_SEMT_FLOCK) fdsem = mc->mc_fdsem; #endif #if defined(MM_SEMT_IPCSEM) fdsem_rd = mc->mc_fdsem_rd; #endif #if defined(MM_SEMT_FLOCK) fdsem = mm_core_getfdsem(mc); #endif #if defined(MM_SHMT_MMFILE) memcpy(fnmem, mc->mc_fnmem, MM_MAXPATH); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) memcpy(fnsem, mc->mc_fnsem, MM_MAXPATH); #endif #if defined(MM_SHMT_MMANON) || defined(MM_SHMT_MMPOSX) || defined(MM_SHMT_MMZERO) || defined(MM_SHMT_MMFILE) munmap((caddr_t)mc, size); #endif #if defined(MM_SHMT_IPCSHM) shmdt((void *)mc); shmctl(fdmem, IPC_RMID, NULL); #endif #if defined(MM_SHMT_MMFILE) unlink(fnmem); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) close(fdsem); #endif #if defined(MM_SEMT_FLOCK) || defined(MM_SEMT_FCNTL) unlink(fnsem); #endif #if defined(MM_SEMT_IPCSEM) semctl(fdsem, 0, IPC_RMID, 0); semctl(fdsem_rd, 0, IPC_RMID, 0); #endif return; }
int ipcrm_main(int argc, char **argv) { int c; int error = 0; /* if the command is executed without parameters, do nothing */ if (argc == 1) return 0; #ifndef CONFIG_IPCRM_DROP_LEGACY /* check to see if the command is being invoked in the old way if so then run the old code. Valid commands are msg, shm, sem. */ { type_id what = 0; /* silence gcc */ char w; w=argv[1][0]; if ( ((w == 'm' && argv[1][1] == 's' && argv[1][2] == 'g') || (argv[1][0] == 's' && ((w=argv[1][1]) == 'h' || w == 'e') && argv[1][2] == 'm') ) && argv[1][3] == '\0' ) { if (argc < 3) bb_show_usage(); if (w == 'h') what = SHM; else if (w == 'm') what = MSG; else if (w == 'e') what = SEM; if (remove_ids(what, argc-2, &argv[2])) fflush_stdout_and_exit(1); printf("resource(s) deleted\n"); return 0; } } #endif /* #ifndef CONFIG_IPCRM_DROP_LEGACY */ /* process new syntax to conform with SYSV ipcrm */ while ((c = getopt(argc, argv, "q:m:s:Q:M:S:h?")) != -1) { int result; int id = 0; int iskey = (isupper)(c); /* needed to delete semaphores */ union semun arg; arg.val = 0; if ((c == '?') || (c == 'h')) { bb_show_usage(); } /* we don't need case information any more */ c = tolower(c); /* make sure the option is in range: allowed are q, m, s */ if (c != 'q' && c != 'm' && c != 's') { bb_show_usage(); } if (iskey) { /* keys are in hex or decimal */ key_t key = xstrtoul(optarg, 0); if (key == IPC_PRIVATE) { error++; bb_error_msg("illegal key (%s)", optarg); continue; } /* convert key to id */ id = ((c == 'q') ? msgget(key, 0) : (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0)); if (id < 0) { char *errmsg; const char * const what = "key"; error++; switch (errno) { case EACCES: errmsg = "permission denied for"; break; case EIDRM: errmsg = "already removed"; break; case ENOENT: errmsg = "invalid"; break; default: errmsg = "unknown error in"; break; } bb_error_msg("%s %s (%s)", errmsg, what, optarg); continue; } } else { /* ids are in decimal */ id = xatoul(optarg); } result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) : (c == 'm') ? shmctl(id, IPC_RMID, NULL) : semctl(id, 0, IPC_RMID, arg)); if (result) { char *errmsg; const char * const what = iskey ? "key" : "id"; error++; switch (errno) { case EACCES: case EPERM: errmsg = "permission denied for"; break; case EINVAL: errmsg = "invalid"; break; case EIDRM: errmsg = "already removed"; break; default: errmsg = "unknown error in"; break; } bb_error_msg("%s %s (%s)", errmsg, what, optarg); continue; } } /* print usage if we still have some arguments left over */ if (optind != argc) { bb_show_usage(); } /* exit value reflects the number of errors encountered */ return error; }