2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
14 * Copyright 1998-2002 Heiko Eissfeldt
19 /* -------------------------------------------------------------------- */
21 /* -------------------------------------------------------------------- */
22 /* int seminstall(key,amount) */
23 /* int semrequest(semid,semnum) */
24 /* int semrelease(semid,semnum) */
25 /* -------------------------------------------------------------------- */
29 #if !defined(HAVE_SMMAP) && !defined(HAVE_USGSHM) && !defined(HAVE_DOSALLOCSHAREDMEM) && !defined(HAVE_AREAS)
30 #undef FIFO /* We cannot have a FIFO on this platform */
33 #if !defined(USE_MMAP) && !defined(USE_USGSHM)
37 #if !defined HAVE_SMMAP && defined FIFO
39 # define USE_USGSHM /* SYSV shared memory is the default */
42 #ifdef USE_MMAP /* Only want to have one implementation */
43 # undef USE_USGSHM /* mmap() is preferred */
46 #ifdef HAVE_DOSALLOCSHAREDMEM
50 # undef USE_BEOS_AREAS
57 # define USE_BEOS_AREAS
68 #if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
69 #include <sys/types.h>
74 #if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1)
75 #include <sys/types.h>
81 #if defined(HAVE_SMMAP) && defined(USE_MMAP)
86 #include <usal/scsitransp.h>
89 #include <be/kernel/OS.h>
93 #include "interface.h"
96 #include "exitcodes.h"
104 int flush_buffers(void);
107 /*------ Semaphore interfacing (for special cases only) ----------*/
108 /*------ Synchronization with pipes is preferred ----------*/
110 #if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
113 static int seminstall(key_t key, int amount);
115 static int seminstall(key_t key, int amount)
120 semflag = IPC_CREAT | 0600;
122 fprintf(stderr,"seminstall: key: %d, #sems %d, flags %4x\n",
125 ret_val = semget(key,amount,semflag);
128 fprintf(stderr,"semget: (Key %lx, #%d) failed: ",
135 /*-----------------------------------------------------------------*/
136 int semrequest(int semid, int semnum)
138 struct sembuf sops[1];
142 fprintf(stderr,"pid %d, ReQuest id:num %d:%d\n",getpid(),semid,semnum);
145 sops[0].sem_num = (short) semnum;
150 ret_val = semop(semid,sops,1);
151 if (ret_val == -1 && errno != EAGAIN && errno != EINTR)
153 fprintf(stderr,"Request Sema %d(%d) failed: ",semid,semnum);
156 } while (errno == EAGAIN || errno == EINTR);
160 /*-----------------------------------------------------------------*/
161 int semrelease(int semid, int semnum, int amount)
163 struct sembuf sops[1];
167 fprintf(stderr,"%d RL %d:%d\n",getpid(),semid,semnum);
169 sops[0].sem_op = amount;
170 sops[0].sem_num = (short) semnum;
172 ret_val = semop(semid,sops,1);
173 if ( ret_val == -1 && errno != EAGAIN)
175 fprintf(stderr,"Release Sema %d(%d) failed: ",semid,semnum);
186 /*------ Synchronization with pipes ----------*/
192 if (pipe(pipefdp2c) < 0) {
193 perror("cannot create pipe parent to child");
196 if (pipe(pipefdc2p) < 0) {
197 perror("cannot create pipe child to parent");
214 int semrequest(int dummy, int semnum)
217 if (semnum == FREE_SEM /* 0 */) {
219 if ((*total_segments_read) - (*total_segments_written) >= global.buffers) {
220 /* parent/reader waits for freed buffers from the child/writer */
222 retval = read(pipefdp2c[0], &dummy, 1) != 1;
228 if ((*total_segments_read) == (*total_segments_written)) {
229 /* child/writer waits for defined buffers from the parent/reader */
231 retval = read(pipefdc2p[0], &dummy, 1) != 1;
239 int semrelease(int dummy, int semnum, int amount)
241 if (semnum == FREE_SEM /* 0 */) {
242 if (*parent_waits == 1) {
244 /* child/writer signals freed buffer to the parent/reader */
246 retval = write(pipefdp2c[1], "12345678901234567890", amount) != amount;
250 if (*child_waits == 1) {
252 /* parent/reader signals defined buffers to the child/writer */
254 retval = write(pipefdc2p[1], "12345678901234567890", amount) != amount;
263 if ((*total_segments_read) > (*total_segments_written)) {
264 return write(pipefdc2p[1], "1", 1) != 1;
271 /*------------------- Shared memory interfacing -----------------------*/
275 #if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1)
276 static int shm_request_nommap(int size, unsigned char **memptr);
278 /* request a shared memory block */
279 static int shm_request_nommap(int size, unsigned char **memptr)
286 key_t key = IPC_PRIVATE;
288 shmflag = IPC_CREAT | 0600;
289 ret_val = shmget(key,size,shmflag);
298 ret_val = shmctl(SHMEM_ID,cmd,&buf);
300 fprintf(stderr, "%d: shmctl STAT= %d, SHM_ID: %d, key %ld cuid %d cgid %d mode %3o size %d\n",
301 getpid(),ret_val,SHMEM_ID,
302 (long) buf.shm_perm.key,buf.shm_perm.cuid,buf.shm_perm.cgid,
303 buf.shm_perm.mode,buf.shm_segsz);
306 *memptr = (unsigned char *) shmat(SHMEM_ID, NULL, 0);
307 if (*memptr == (unsigned char *) -1) {
309 fprintf( stderr, "shmat failed for %d bytes\n", size);
313 if (shmctl(SHMEM_ID, IPC_RMID, 0) < 0) {
314 fprintf( stderr, "shmctl failed to detach shared memory segment\n");
320 start_of_shm = *memptr;
321 end_of_shm = (char *)(*memptr) + size;
323 fprintf(stderr, "Shared memory from %p to %p (%d bytes)\n", start_of_shm, end_of_shm, size);
329 #endif /* #if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1) */
332 static int shm_request(int size, unsigned char **memptr);
335 /* request a shared memory block */
336 static int shm_request(int size, unsigned char **memptr)
338 return shm_request_nommap(size, memptr);
342 /* release semaphores */
346 #if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
348 union my_semun unused_arg;
352 /* HP-UX warns here, but 'unused_arg' is not used for this operation */
353 /* This warning is difficult to avoid, since the structure of the union
354 * generally is not known (os dependent). So we cannot initialize it
357 semctl(sem_id,0,mycmd,unused_arg);
363 #if defined(HAVE_SMMAP)
366 /* request a shared memory block */
367 static int shm_request(int size, unsigned char **memptr)
372 #ifdef MAP_ANONYMOUS /* HP/UX */
374 addr = mmap(0, mmap_sizeparm(size), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, f, 0);
376 if ((f = open("/dev/zero", O_RDWR)) < 0)
377 comerr("Cannot open '/dev/zero'.\n");
378 addr = mmap(0, mmap_sizeparm(size), PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
381 if (addr == (char *)-1) {
382 #if defined HAVE_SHMAT && (HAVE_SHMAT == 1)
383 unsigned char *address;
384 /* fallback to alternate method */
385 if (0 != shm_request_nommap(size, &address) || (addr = (char *)address) == NULL)
387 comerr("Cannot get mmap for %d Bytes on /dev/zero.\n", size);
392 *memptr = (unsigned char *)addr;
396 #endif /* HAVE_SMMAP */
397 #endif /* USE_MMAP */
401 /* request a shared memory block */
402 static int shm_request(int size, unsigned char **memptr)
407 * The OS/2 implementation of shm (using shm.dll) limits the size of one
408 * memory segment to 0x3fa000 (aprox. 4MBytes). Using OS/2 native API we
409 * no such restriction so I decided to use it allowing fifos of arbitrary size
411 if(DosAllocSharedMem(&addr,NULL,size,0X100L | 0x1L | 0x2L | 0x10L))
412 comerr("DosAllocSharedMem() failed\n");
415 *memptr = (unsigned char *)addr;
421 #ifdef USE_BEOS_AREAS
423 /* request a shared memory block */
424 static int shm_request(int size, unsigned char **memptr)
427 area_id aid; /* positive id of the mapping */
429 /* round up to a multiple of pagesize. */
430 size = ((size - 1) | (B_PAGE_SIZE - 1)) + 1;
432 * request a shared memory area in user space.
434 aid = create_area(AREA_NAME, /* name of the mapping */
435 (void *)&addr, /* address of shared memory */
436 B_ANY_ADDRESS, /* type of address constraint */
437 size, /* size in bytes (multiple of pagesize) */
438 B_NO_LOCK, /* B_FULL_LOCK, */ /* memory locking */
439 B_READ_AREA | B_WRITE_AREA); /* read and write permissions */
442 comerrno(aid, "create_area() failed\n");
445 *memptr = (unsigned char *)addr;
451 void *request_shm_sem(unsigned amount_of_sh_mem, unsigned char **pointer)
453 #if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
454 /* install semaphores for double buffer usage */
455 sem_id = seminstall(IPC_PRIVATE,2);
456 if ( sem_id == -1 ) {
457 perror("seminstall");
458 exit(SEMAPHORE_ERROR);
464 if (-1 == shm_request(amount_of_sh_mem, pointer)) {
465 perror("shm_request");