/* ** shm.c: ** a quick solution for multi-process(or) shared memory ** programming using UNIX fork(), shmop(), semop(), and ** mixed Fotran and C coding. Perhaps the quickest way ** to convert a brute force f77 code to work in one box ** parallelly and retain its efficiency. ** ** Li Ju. May 27, 1997. */ #include #include #include #include #include #include #include /* define common variables */ key_t shm_KEY; /* shared memory key */ int shm_ID; /* shared memory ID */ double *shm_block; /* shared memory logical address */ double *u,*u2,*u4,*u6,*u8,*u10,*uold,*copy; volatile char *schedule_flags; /* Must be volatile because after optimization one process might chosen to only read schedule_flags[*My_idx-1] once into register, as there is no "explicit" data dependence. */ #define U_TO_U2 1 #define U2_TO_U4 2 #define U4_TO_U6 3 #define U6_TO_U8 4 #define U8_TO_U10 5 #define COLLECT_MY_DOMAIN_TO_U2 11 #define COLLECT_MY_DOMAIN_TO_U4 12 #define COLLECT_MY_DOMAIN_TO_U6 13 #define COLLECT_MY_DOMAIN_TO_U8 14 #define COLLECT_MY_DOMAIN_TO_U10 15 #define TRANSFER_FROM_V 21 #define TRANSFER_TO_V 22 #define SLAVE_DIE 99 /* addresses of passed array arguments: actually */ /* pseudonames for u's in the main program */ double **v; double **v2; double **v4; double **v6; double **v8; double **v10; int size_of_vector_in_bytes; int size_of_vector_in_double; double * address_u; /* link with fortran common block "offset" to provide handles for fortran use */ extern struct { int SU,SU2,SU4,SU6,SU8,SU10,SCOPY; } offset_ ; /* link with fortran common block "layout" */ extern struct { int num_processors; int domain; } layout_ ; int *domain; key_t sem_KEY; /* semaphore key */ int sem_ID; /* semaphore ID */ volatile struct sembuf semop_add, semop_minus, semop_zero; volatile union semun { int val; struct semid_ds *buf; ushort *array; } sem_set; void Error(const char *fmt,...) { printf("Error:%s(%s)\n",fmt,strerror(errno)); } int generate_and_init_semaphore_ (int *num_processors) { int i; for (sem_KEY=1; ((sem_ID=semget(sem_KEY,(*num_processors),IPC_CREAT|0600))==-1) &&(sem_KEY<65535); sem_KEY++); if(sem_ID!=-1) { /* define semaphore operations */ semop_add.sem_op = +1; semop_add.sem_flg = 0600; semop_minus.sem_op = -1; semop_minus.sem_flg = 0600; semop_zero.sem_op = 0; semop_zero.sem_flg = 0600; /* hypnotize the slave processes first */ for (i=1;i1) master_set_command (SLAVE_DIE); } void free_shm_block_() { shmctl (shm_ID,IPC_RMID,NULL); return; }