#include #include #include #include #include #include #include #include #include volatile int stop = 0, signalled = 0; void handle_usr1(int x) { signalled = 1; } void handle_ctrlc(int x) { stop = 1; } void setup(int sig, void (* handler)(int)) { struct sigaction sa; sa.sa_handler = handler; sa.sa_flags = 0; sigemptyset(& sa.sa_mask); int r = sigaction(sig, & sa, NULL); if (r < 0) { perror("sigaction failed"); exit(1); } } void P(long long int * mutexptr) { long long int val = 1; while (1) { asm volatile ( "mov $1, %%rax \n" "mov %[mutexptr], %%rbx \n" "lock xchg %%rax, (%%rbx) \n" "mov %%rax, %[val] \n" : [val] "=m" (val) : [mutexptr] "m" (mutexptr) : "rax", "rbx", "cc", "memory" ); if (val) usleep(1000); else break; } } void V(long long int * mutex) { * mutex = 0; } int main(int argc, char * argv[]) { int otherpid, clear = 0; printf("my pid is %d\n", getpid()); if (argc == 1 || argc == 2 && strcmp(argv[1], "clear") == 0) { if (argc == 2) clear = 1; printf("other process' pid? "); scanf("%d", & otherpid); } else otherpid = atol(argv[1]); setup(SIGUSR1, handle_usr1); setup(SIGINT, handle_ctrlc); int f = shm_open("/home/students/sratbag/421/shmem/shm.02", O_RDWR | O_CREAT | O_EXCL, 0644); if (f >= 0) clear = 1; else { f = shm_open("/home/students/sratbag/421/shmem/shm.02", O_RDWR, 0644); if (f < 0) { perror("shm_open failed"); exit(1); } } ftruncate(f, 1024); char * p = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0); if (clear) bzero(p, 1024); long long int * mutex_ptr = (long long int *) p; long long int * message_ready_ptr = (long long int *) (p + sizeof(long long int)); char * message = p + 2 * sizeof(long long int); char typed[128]; while (! stop) { int n = read(0, typed, 127); if (n < 0) { if (! signalled) { perror("read failed"); usleep(10000); continue; } signalled = 0; if (stop) break; P(mutex_ptr); if (* message_ready_ptr) { printf("%s", message); * message_ready_ptr = 0; } V(mutex_ptr); continue; } typed[n] = '\0'; if (strcmp(typed, "exit\n") == 0) break; int done = 0; while (! done) { P(mutex_ptr); if (* message_ready_ptr) done = 0; else { strcpy(message, typed); * message_ready_ptr = 1; done = 1; } V(mutex_ptr); if (! done) usleep(1000); } int r = kill(otherpid, SIGUSR1); if (r < 0) perror("kill failed"); } f = shm_unlink("/home/students/sratbag/421/shmem/shm.02"); if (f < 0) { perror("shm_unlink failed"); exit(1); } }