int main(int argc, char *argv[]) { pid = getpid(); chid = ChannelCreate(0); if (argc != 4) { printf("Proper usage: ./lab2 range_start range_end thread_count\n"); return 0; } int range_start = atoi(argv[1]); int range_end = atoi(argv[2]); int threads_count = atoi(argv[3]); int range_length = (range_end - range_start) / (threads_count * 4); int i = 0; int f = 0; pthread_t tid; while (1) { if (running_threads < threads_count && !f) { pthread_create(&tid, NULL, count_primes2, NULL); running_threads++; continue; } else { f = 1; par_t args; int rcvid = MsgReceive(chid, &args, sizeof(args), NULL); if (range_start + (i + 1) * range_length <= range_end) { if (args.typ == 10) { args.typ = 1; args.numer = i; args.pocz = range_start + i * range_length; args.kon = range_start + (i + 1) * range_length; int status = MsgReply(rcvid, EOK, &args, sizeof(args)); if (-1 == status) { perror("MsgReply"); } } i++; } else { args.typ = 0; int status = MsgReply(rcvid, EOK, &args, sizeof(args)); if (-1 == status) { perror("MsgReply"); } printf("Watek %d poprosil, ale nie ma\n", args.numer); running_threads--; if (!running_threads) { break; } } } } printf("Liczb pierwszych: %d\n", p_count); return 0; }
int main(int argc, char *argv[]) { pid_t pid_2 = getpid(); pid_t pid_1 = getppid(); char *msg = (char*)malloc(BUFFER_LENGTH*sizeof(char)); char *rmsg = (char*)malloc(BUFFER_LENGTH*sizeof(char)); printf(" P2>\n"); printf(" P2> Parent pid: %i\n", pid_1); int chidP1 = atoi(argv[0]); // Step 3 Creating channel - chidP2. int chidP2 = ChannelCreate(0); printf(" P2> pid: %i, P1 chid: %i, P2 chid: %i\n", pid_2, chidP1, chidP2); // Step 4 Spawning P3 process - pid_3. char argv0[12]; sprintf(argv0, "%i", chidP2); int pid_3 = spawnl(P_NOWAITO, "/tmp/M3", argv0, NULL); // Step 6 Sending chidP2 to P1. int coid_1 = ConnectAttach(ND_LOCAL_NODE, pid_1, chidP1, _NTO_SIDE_CHANNEL, 0); if (coid_1==-1) { fprintf(stderr, "Connection error.\n"); exit(EXIT_FAILURE); } printf(" P2> P2 coid: %i\n", coid_1); int msg_res = MsgSend(coid_1, &chidP2, sizeof(int), rmsg, BUFFER_LENGTH*sizeof(char)); //sizeof(bytes) if (msg_res < 0) { msg_res = errno; fprintf(stderr, " P2> Error MsgSend\n"); fprintf(stderr, " P2> Error code:%i\n", msg_res); exit(EXIT_FAILURE); } printf(" P2> Server replied \n%s\n", rmsg); // Step 8 Receiving query from P3. int rcvid = MsgReceive(chidP2, msg, sizeof(msg), NULL); printf(" P2> Received, rcvid: %i\n", rcvid); printf(" P2> Message: %s\n", msg); // Step 9 Replying to P3. Sending pid_1 and chidP1. *(int*)((int)msg) = pid_1; *(int*)((int)msg + 4) = chidP1; MsgReply(rcvid, EOK, msg, 8); // Step 12 Receiving message from P1. Reply. rcvid = MsgReceive(chidP2, msg, sizeof(msg), NULL); printf(" P2> Received, rcvid: %i\n", rcvid); printf(" P2> Message: %s\n", msg); strcpy(msg, "P2 OK"); MsgReply(rcvid, EOK, msg, strlen(msg) + 1); printf(" P2> Good luck!\n"); return EXIT_SUCCESS; }
/** * This function represents server thread. Thanks to this function we can * receive data send by client. * * @param nth - not used but demanded by pthread_create() convencion * @return no value returned */ void* receive (void* nth) { my_data_t msg; int rcvid; /* Trying to register and create channel */ if ((attach = name_attach(NULL, my_channel, 0)) == NULL) { std::cerr<< "Can't create Channel\n"; exit(-1); } /* main loop - receiving messages */ while(true) { rcvid = MsgReceive(attach->chid, &msg, sizeof(msg), NULL); /* checking if message was received correctly */ if (rcvid == -1) { std::cerr<<"Error in receiving message. \n"; break; } /* checking if message is a pulse */ if (rcvid == 0) { switch (msg.header.code) { case _PULSE_CODE_DISCONNECT: /* Canceling client thread */ pthread_cancel(client); /* Waiting for thread to finish executing */ pthread_join(client, NULL); /* Closing connection and destroying channel */ name_close(coid); name_detach(attach, 0); /* Finish server thread */ pthread_exit (0); } } /* check if message is connection request */ if (msg.header.type == _IO_CONNECT) { MsgReply(rcvid, EOK, NULL, 0); continue; } /* chcek id message is unimplemented system communicate */ if (msg.header.type > _IO_BASE && msg.header.type <= _IO_MAX) { MsgError (rcvid, ENOSYS); continue; } printf("\n"); printf("[%s]: %s\n", stranger_channel, msg.data); printf("[%s]: ", my_channel); fflush(stdout); //std::cout<<"Server received: " << msg.data<< "\n "; MsgReply(rcvid, EOK, NULL, 0); } }
//Creates msg server //Performs communication with client int message_server(){ printf("I am now a server \n"); int channelID, clientID; channelID = ChannelCreate(0); struct _msg_info client_info; while(1){ clientID = MsgReceive(channelID, &buffer, sizeof buffer, &client_info); //Print client info printf("CLIENT INFO: \n"); printf("received msg on channel: %d\n", client_info.chid); printf("from client with ID: %d\n", client_info.pid); printf("Received msg of length: %d\n", client_info.msglen); //Perform some task for client printf("client sent: %c \n\n", buffer[0]); buffer[0] = 'S'; //reply to client int someKindOfReturn; someKindOfReturn = MsgReply(clientID, EOK, &buffer, sizeof buffer); } //Unnecessary return return channelID; }
int io_write(resmgr_context_t *ctp, io_write_t *msg, iofunc_ocb_t *ocb) { int status; int nonblock; unsigned cnt; // Is device open for write? if((status = iofunc_write_verify(ctp, msg, ocb, &nonblock)) != EOK) return status; // No special xtypes if((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) return(EINVAL); // Writes must be between 3 and 255 ints msg->i.nbytes = (msg->i.nbytes + (sizeof(int) - 1)) & ~(sizeof(int) - 1); if(msg->i.nbytes < _SLOG_MINSIZE || msg->i.nbytes > _SLOG_MAXSIZE) return(EINVAL); cnt = msg->i.nbytes/sizeof(int); /* PR 26878 To avoid priority inversion reply to 'writer' immediately. */ MsgReply(ctp->rcvid, msg->i.nbytes, NULL, 0); _io_write_log(ctp, msg, ocb, cnt, 0); return(_RESMGR_NOREPLY); }
int io_write(resmgr_context_t *ctp, io_write_t *msg, iofunc_ocb_t *ocb) { LOCK(resource_mutex); printf("IO write activated\n"); // set data to return _IO_SET_WRITE_NBYTES(ctp, msg->i.nbytes); int nBytes = msg->i.nbytes + 1; char *buf = (char *)malloc(nBytes * sizeof(char)); if (!buf) RETURN_UNLOCK(ENOMEM, resource_mutex); resmgr_msgread(ctp, buf, nBytes, sizeof(msg->i)); buf[msg->i.nbytes] = '\0'; printf("Received %d bytes = \"%s\"\n", msg->i.nbytes, buf); int rcvid = fifo_rem_blocked_id(fifoHandler); if(rcvid != -1) { printf("Found blocked id, sending string '%s' with %i bytes\n", buf, nBytes); MsgReply(rcvid, nBytes, buf, nBytes); free(buf); RETURN_UNLOCK(_RESMGR_NPARTS(0), resource_mutex); } fifo_add_string(fifoHandler, buf); free(buf); RETURN_UNLOCK(_RESMGR_NPARTS(0), resource_mutex); }
int main( int argc, char** argv ) { int fd, FileDescriptor, FileSize = 0; unsigned *addr; int ChannelID, SenderID; int counter = 0; /* Open a file for copying*/ FileDescriptor = open("Goodtimes.mpg", O_RDONLY); FileSize = lseek(FileDescriptor, 0, SEEK_END); char* File = new char[FileSize]; lseek(FileDescriptor, 0, SEEK_SET); read(FileDescriptor, File, FileSize); /* Create a new memory object */ fd = shm_open( "/MySharedMemory", O_RDWR | O_CREAT, 0777 ); if( fd == -1 ) { printf("error: couldn't create a shared memory object\n"); return 1; } /* Set the memory object's size */ if( ftruncate( fd, FileSize) == -1 ) { printf("error: couldn't set the size\n"); return 1; } /* Map the memory object */ addr = (unsigned*) mmap( 0, FileSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if( addr == MAP_FAILED ) { printf("error: mapping in the memory failed\n"); return 1; } printf( "memory mapping address is 0x%08x\n", addr ); ChannelID = ChannelCreate(NULL); *(addr + 0) = getpid(); // needed by client to set up connection for synchronization *(addr + 1) = ChannelID; *(addr + 2) = FileSize; while(1) { SenderID = MsgReceive(ChannelID, NULL, 0, NULL); // block until client blocks /* Write to shared memory */ memcpy(addr, File, FileSize); MsgReply(SenderID, 0, NULL, 0); // awake client to read shared memory } close( fd ); shm_unlink( "/MySharedMemory" ); return 0; }
int main(int argc, char *argv[]) { printf("Server started \n"); /* Create shared memory */ int file_descriptor; file_descriptor = shm_open("/sharedpid", O_RDWR | O_CREAT, S_IRWXU); /* Resize shared memory */ ftruncate(file_descriptor, sizeof(pid_data)); /* Map shared memory into address space */ void* shared_memory; shared_memory = mmap(0, sizeof(pid_data), PROT_READ | PROT_WRITE, MAP_SHARED, file_descriptor, 0); /* Create struct */ pid_data data; data.pid = getpid(); /* Create Mutex */ pthread_mutex_t lock = ((pid_data*)shared_memory)->pid_mutex; pthread_mutexattr_t myattr; pthread_mutexattr_init(&myattr); pthread_mutexattr_setpshared(&myattr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&lock, &myattr ); /* Set pid in shared memory */ pthread_mutex_lock(&lock); *((pid_data*)shared_memory) = data; pthread_mutex_unlock(&lock); printf("Pid stored in shared memory \n"); /* Create channel */ int ch_id = ChannelCreate(0); printf("Channel %d created \n", ch_id); int rcv_id; int buffer_recv; int buffer_resp; struct _msg_info msg_info; /* Set priority */ set_priority(SERVER_PRIORITY); /* Listen for client */ printf("Server listening... \n"); while(1){ printf("Server priority: %d\n", get_priority()); rcv_id = MsgReceive(ch_id, &buffer_recv, sizeof(buffer_recv), &msg_info); buffer_resp = buffer_recv + 1; printf("Received: %d, Responding: %d \n", buffer_recv, buffer_resp); if(MsgReply(rcv_id, EOK, &buffer_resp, sizeof(buffer_resp)) != EOK){ printf("ERROR: failed to reply to message: %d \n", buffer_recv); } } return EXIT_SUCCESS; }
static int process_read_data(int rcvid, devi_attr_t *attr, devi_ocb_t *ocb, int nbytes) { int q_size; int num_req_packets; int num_pkts_xfer; int num_pkts_end; iov_t iov[3]; int parts = 1; char *ptr = NULL; event_bus_line_t *line = attr->line; if (line->head > ocb->read_ptr) q_size = line->head - ocb->read_ptr; else q_size = RESMGR_Q_SIZE - ocb->read_ptr + line->head; num_req_packets = nbytes / line->elem_size; if (num_req_packets == 0) MsgReply(rcvid, EOK, NULL, 0); if (q_size < num_req_packets) { return (-1); } num_pkts_xfer = min(num_req_packets, q_size); num_pkts_end = RESMGR_Q_SIZE - ocb->read_ptr; switch(line->type) { case DEVI_CLASS_KBD: ptr = (char *) line->u.kq; break; case DEVI_CLASS_REL: ptr = (char *) line->u.mq; break; case DEVI_CLASS_ABS: ptr = (char *) line->u.tq; break; } if (num_pkts_end >= num_pkts_xfer) SETIOV(&iov[0], ptr + line->elem_size * ocb->read_ptr, num_pkts_xfer * line->elem_size); else { SETIOV(&iov[0], ptr + line->elem_size * ocb->read_ptr, num_pkts_end * line->elem_size); num_pkts_xfer -= num_pkts_end; SETIOV(&iov[1], ptr, num_pkts_xfer * line->elem_size); parts = 2; } MsgReplyv(rcvid, num_pkts_xfer * line->elem_size, iov, parts); ocb->read_ptr = (ocb->read_ptr + num_pkts_xfer) % RESMGR_Q_SIZE; return (EOK); }
int main(int argc, char *argv[]) { int chid; // Kanal komunikacyjny pid_t pid; // PID serwera int rcvid; // identifikator nadawcy struct _msg_info info; int checksum; // liczba znakow w odebranej wiadomosci int status = 0; struct _pulse msg; chid = ChannelCreate(0); if (chid == -1) { printf("\tS: Nie moge utworzyc kanalu: %s\n", strerror(errno)); return EXIT_FAILURE; } pid = getpid(); printf("\tS: PID serwera: %d, CHID: %d\n", pid, chid); while(1) { /* Odebranie impulsu */ rcvid = MsgReceive(chid, &msg, sizeof(msg), &info); /* Jesli nie udalo sie pobrac wiadomosci */ if(rcvid == -1) { printf("\tS: Nie moge odebrac wiadomosci: %s\n", strerror(errno)); break; // sprobuj odebrac inna wiadomosc } else if (rcvid == 0) { printf("\tS: Odebralem impuls.\n\tS: Kod impulsu: %d, wartosc %d\n", msg.code, msg.value.sival_int); continue; } checksum = msg.value.sival_int; /* odpowiedz klientowi, jesli komunikat */ MsgReply(rcvid,status,&checksum,sizeof(checksum)); if(status == -1) { printf("\tS: Nie moge odpowiedziec: %s\n", strerror(errno)); } } return EXIT_SUCCESS; }
static int devi_unblock(resmgr_context_t *ctp, io_pulse_t *msg, RESMGR_OCB_T *ocb) { devi_attr_t *attr = ocb->ocb.attr; struct _wait_q *wp; for (wp = attr->wait_queue; wp; wp = wp->next) { if (wp->ocb == ocb) { MsgReply(wp->rcvid, EINTR, NULL, 0); remove_wait_queue(attr, wp); break; } } return (iofunc_unblock_default(ctp, msg, &ocb->ocb)); }
void *server(int server_priority) { int rcvid, status; char myRMessage[BUFSIZE]; struct _msg_info my_msg_info; pid = getpid(); chid = ChannelCreate(NULL); if (chid == -1) { perror("error creating a channel\n"); exit(EXIT_FAILURE); } printf("the server started with pid: %d, chid: %d, priority: %d" , pid, chid, server_priority); while(1) { rcvid = MsgReceive(chid, myRMessage, BUFSIZE, &my_msg_info); printf("the server received message from %d with priority %d\n",my_msg_info.tid, my_msg_info.priority); printf("before server working for %d", my_msg_info.tid); working(my_msg_info.tid); printf("after server working for %d", my_msg_info.tid); status = MsgReply(rcvid, 0, NULL, 0); if (status == -1) { perror("error in reply\n"); exit(EXIT_FAILURE); } printf("the server replied to %d.\n", my_msg_info); } return; }
int main(void) { int rcvid; msg_buf_t msg; int status; int checksum; name_attach_t* attach; setvbuf (stdout, NULL, _IOLBF, 0); //set IO to stdout to be line buffered attach = name_attach(NULL, SERVER_NAME, 0);//PUT CODE HERE to attach a name if(NULL == attach) { //was there an error creating the channel? perror("name_attach()"); //look up the errno code and print exit(EXIT_FAILURE); } while(1) { rcvid = MsgReceive(attach->chid, &msg, sizeof msg, NULL);//PUT CODE HERE to receive msg from client, store the receive id in rcvid if(rcvid == -1) { //was there an error receiving msg? perror("MsgReceive"); //look up errno code and print continue; //try receiving another msg } else if(rcvid == 0) { printf("received pulse, code = %d\n", msg.pulse.code); continue; } printf("received msg: %s\n", msg.cksum.string_to_cksum); checksum = calculate_checksum(msg.cksum.string_to_cksum); status = MsgReply(rcvid, EOK, &checksum, sizeof checksum);//PUT CODE HERE TO reply to client with checksum, store the return status in status if(-1 == status) { perror("MsgReply"); } } return 0; }
int main(int argc, char* argv[]) { int chid; int pid; int rcvid; int status; kom_t msg; int child_count = atoi(argv[1]); chid = ChannelCreate(0); if(-1 == chid) { perror("ChannelCreate()"); exit(EXIT_FAILURE); } pid = getpid(); printf("Server's pid: %d, chid: %d\n", pid, chid); int i = 0; for(i = 0; i < child_count; i++) { int child_pid = fork(); if (!child_pid) { char pid_chars[20]; char chid_chars[20]; int base = 10; itoa(pid, pid_chars, base); itoa(chid, chid_chars, base); execl (CHILD, CHILD, pid_chars, chid_chars, (char *)NULL); } } while(1) { rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL); if(rcvid == -1) { perror("MsgReceive"); break; } if(msg.type == 0) { printf("\tProces %d wyslal zakonczenie\n", msg.from); status = MsgReply(rcvid, EOK, &msg, sizeof(msg) ); if(-1 == status) { perror("MsgReply"); } child_count--; if(child_count == 0) { break; } continue; } printf("%s", msg.text); int i; int lowcase_count = 0; for (i = 0; msg.text[i]; i++) { if(msg.text[i] != toupper(msg.text[i]) && msg.text[i] != '\n') { msg.text[i] = toupper(msg.text[i]); lowcase_count++; } } msg.from = getpid(); msg.type = 1; status = MsgReply(rcvid, EOK, &msg, sizeof(msg) ); if(-1 == status) { perror("MsgReply"); } } printf("po petli\n"); while((pid=wait(&status))!=-1) { printf("Proces %d zakonczony, status %d\n",pid,WEXITSTATUS(status)); } return 0; }
/* * Return -1 * This prp can never match the criteria * Return 0 * This prp does not currently match the criteria * Return WNOHANG * An error with wap, reply was done (i.e. a thread unblocked) * Return non-zero W????? * This prp matched and a reply was done (i.e. a thread unblocked) */ int procmgr_wait_check(PROCESS *prp, PROCESS *parent, struct wait_entry *wap, int match) { struct _msg_info info; /* * Check if this prp matched the requested group */ switch(wap->idtype) { case P_ALL: break; case P_PID: if(prp->pid != wap->id) { return -1; } break; case P_PGID: if(prp->pgrp != wap->id) { return -1; } break; default: MsgError(wap->rcvid, EINVAL); return WNOHANG; } if(match) { /* * Check for match, if parent is ignoring SIGCHLD, are we the last child? */ match &= wap->options; if(wap->idtype == P_ALL && (prp->sibling || parent->child != prp) && sigismember(&parent->sig_ignore, SIGCHLD)) { match &= ~WEXITED; } /* * Have we already responded with exit code? */ if(!(prp->flags & _NTO_PF_WAITINFO)) { match &= ~WEXITED; } } else { /* * Check if the requested prp currently matches any options */ if((wap->options & WTRAPPED) && (prp->flags & (_NTO_PF_DEBUG_STOPPED | _NTO_PF_PTRACED)) == (_NTO_PF_DEBUG_STOPPED | _NTO_PF_PTRACED)) { match = WTRAPPED; } else if((wap->options & WEXITED) && (prp->flags & _NTO_PF_WAITINFO)) { match = WEXITED; } else if((wap->options & WCONTINUED) && (prp->flags & _NTO_PF_CONTINUED)) { match = WCONTINUED; } else if((wap->options & WUNTRACED) && (prp->flags & _NTO_PF_STOPPED) && prp->siginfo.si_signo != 0) { match = WUNTRACED; } } /* * If no options matched, check if it could ever match options */ if(match == 0) { int options = wap->options; if(prp->flags & (_NTO_PF_ZOMBIE | _NTO_PF_TERMING)) { options &= ~(WUNTRACED|WTRAPPED|WCONTINUED); } if((prp->flags & (_NTO_PF_ZOMBIE | _NTO_PF_WAITINFO)) == _NTO_PF_ZOMBIE) { options &= ~WEXITED; } if((prp->flags & _NTO_PF_NOZOMBIE) || sigismember(&parent->sig_ignore, SIGCHLD)) { options &= ~WEXITED; } if(prp->flags & _NTO_PF_WAITDONE) { options &= ~WEXITED; } if(!(prp->flags & _NTO_PF_PTRACED)) { options &= ~WTRAPPED; } if((options & (WEXITED|WUNTRACED|WTRAPPED|WCONTINUED)) == 0) { return -1; } return 0; } /* * Unblock the waiting thread... */ if(MsgInfo(wap->rcvid, &info) != -1) { siginfo_t siginfo; // unbind and unblock if rcvid is still around if((!parent->wap) || ((parent->wap == wap) && (parent->wap->next == NULL))) { (void)_resmgr_unbind(&info); } siginfo = prp->siginfo; if(siginfo.si_signo != SIGCHLD) { if(prp->flags & _NTO_PF_COREDUMP) { siginfo.si_code = CLD_DUMPED; } else { siginfo.si_code = CLD_KILLED; } siginfo.si_status = siginfo.si_signo; siginfo.si_pid = prp->pid; siginfo.si_signo = SIGCHLD; } if(info.flags & _NTO_MI_ENDIAN_DIFF) { ENDIAN_SWAP32(&siginfo.si_signo); ENDIAN_SWAP32(&siginfo.si_code); ENDIAN_SWAP32(&siginfo.si_errno); ENDIAN_SWAP32(&siginfo.si_pid); ENDIAN_SWAP32(&siginfo.si_status); ENDIAN_SWAP32(&siginfo.si_utime); ENDIAN_SWAP32(&siginfo.si_stime); } MsgReply(wap->rcvid, 0, &siginfo, sizeof siginfo); } else { KerextSlogf( _SLOG_SETCODE( _SLOGC_PROC, 0 ), _SLOG_INFO, "proc_wait_check: MsgInfo() failed, errno=%d", errno); } /* * Clean up prp status if requested so it is not reported again */ if(wap->options & WNOWAIT) { return WNOWAIT; } switch(match) { case WEXITED: if(prp->flags & _NTO_PF_WAITINFO) { parent->kids_running_time += prp->running_time + prp->kids_running_time; parent->kids_system_time += prp->system_time + prp->kids_system_time; prp->flags &= ~_NTO_PF_WAITINFO; prp->flags |= _NTO_PF_WAITDONE; } if(prp->flags & _NTO_PF_ZOMBIE) { MsgSendPulse(PROCMGR_COID, prp->terming_priority, PROC_CODE_TERM, prp->pid); } else { match = WNOWAIT; } break; case WUNTRACED: // also WSTOPPED prp->siginfo.si_signo = 0; break; case WTRAPPED: break; case WCONTINUED: prp->flags &= ~_NTO_PF_CONTINUED; break; default: break; } return match; }
int main(int argc, char *argv[]) { uint32_t l; int id, id2; my_data_t msg; int rcvid; name_attach_t *name; printf("Welcome Onda\n"); if (ThreadCtl(_NTO_TCTL_IO, 0) < 0) { perror(NULL); return -1; } name = name_attach(NULL, "onda", NAME_FLAG_ATTACH_GLOBAL); if (name == NULL) { perror("Error0\n"); return -1; } /* attach GPIO interrupt */ id = InterruptAttach (33, gpio_isr_handler, NULL, 0, _NTO_INTR_FLAGS_PROCESS); /* attach timer interrupt */ id2 = InterruptAttach (45, timer_isr_handler, NULL, 0, _NTO_INTR_FLAGS_PROCESS); gpio5 = mmap_device_io(OMAP3530_GPIO_SIZE, OMAP3530_GPIO5_BASE); if (gpio5 == MAP_DEVICE_FAILED) { perror(NULL); return -1; } //gpt3 = mmap_device_io(OMAP3530_GPT_SIZE, OMAP3530_GPT3_BASE); gpt9 = mmap_device_io(OMAP3530_GPT_SIZE, OMAP3530_GPT9_BASE); if (gpt9 == MAP_DEVICE_FAILED) { perror(NULL); return -1; } sys = mmap_device_io(OMAP3530_SYSCTL_SIZE, OMAP3530_SYSCTL_BASE); if (sys == MAP_DEVICE_FAILED) { perror(NULL); return -1; } /* selecting mode 4 function - GPIO 139 * selecting pullup and mode 4 function - GPIO 138 */ #define SYS_CONF ((4 << 16) | ((1 << 8) | (1<<3) | 4)) #define SYS_MASK ~(0x10F010F) l = (in32(sys + 0x168) & SYS_MASK) | SYS_CONF; //l = (in32(sys + 0x168) & ~(7<<16) ) | (4 << 16); //out32(sys + 0x168, ((1<<3 | 4) << 16) | (1<<3) | 4); out32(sys + 0x168, l); /* setting mode 2 - PWM */ l = (in32(sys + 0x174) & ~7 ) | 2; out32(sys + 0x174, l); /* setting the PIN 138 to input * setting the PIN 139 to output */ l = (in32(gpio5 + OMAP2420_GPIO_OE) & ~(1 << 11)) | 1 << 10; out32(gpio5 + OMAP2420_GPIO_OE, l); /* enabling interrupt on both levels on GPIO 139 */ out32(gpio5 + OMAP2420_GPIO_RISINGDETECT, l << 10); out32(gpio5 + OMAP2420_GPIO_FALLINGDETECT, l << 10); out32(gpio5 + OMAP2420_GPIO_SETIRQENABLE1, l << 10); /* make sure timer has stop */ out32(gpt9 + OMAP3530_GPT_TCLR, 0); /* enabling the interrupt */ out32(gpt9 + OMAP3530_GPT_TIER, 2); //comentar se PWM /* configuring PWM */ out32(gpt9 + OMAP3530_GPT_TCLR, (1<<12) | (1<<10) | (1<<7)); //-- PWM out32(gpio5 + OMAP2420_GPIO_SETDATAOUT, (1 << 11)); printf("Esperando requisições\n"); while (1) { rcvid = MsgReceive(name->chid, &msg, sizeof(msg), NULL); if (rcvid == -1) {/* Error condition, exit */ break; } /* name_open() sends a connect message, must EOK this */ if (msg.hdr.type == _IO_CONNECT) { MsgReply(rcvid, EOK, NULL, 0); continue; } /* Some other QNX IO message was received; reject it */ if (msg.hdr.type > _IO_BASE && msg.hdr.type <= _IO_MAX) { MsgError(rcvid, ENOSYS); continue; } switch (msg.hdr.subtype) { case 0x55: MsgReply(rcvid, EOK, &pincount, sizeof(pincount)); break; case 0x65: MsgReply(rcvid, EOK, &interval, sizeof(interval)); break; case 0x66: interval = msg.data; MsgReply(rcvid, EOK, &interval, sizeof(interval)); break; default: MsgReply(rcvid, EOK, NULL, 0); } } out32(gpt9 + OMAP3530_GPT_TCLR, 0); out32(gpt9 + OMAP3530_GPT_TIER, 0); InterruptDetach (id); InterruptDetach (id2); printf("Fim\n"); return EXIT_SUCCESS; }
int server() { name_attach_t *attach; mss_t msg; mss_t rmsg; //my_data_t msg; int rcvid; /* Create a local name (/dev/name/local/...) */ if ((attach = name_attach(NULL, ATTACH_POINT, 0)) == NULL) { return EXIT_FAILURE; } /* Do your MsgReceive's here now with the chid */ while (1) { rcvid = MsgReceive(attach->chid, &msg, sizeof(msg), NULL); if (rcvid == -1) {/* Error condition, exit */ break; } // if (rcvid == 0) {/* Pulse received */ // switch (msg.hdr.code) { // case _PULSE_CODE_DISCONNECT: /* * A client disconnected all its connections (called * name_close() for each name_open() of our name) or * terminated */ // ConnectDetach(msg.hdr.scoid); // break; // case _PULSE_CODE_UNBLOCK: /* * REPLY blocked client wants to unblock (was hit by * a signal or timed out). It's up to you if you * reply now or later. // */ // break; // default: /* * A pulse sent by one of your processes or a * _PULSE_CODE_COIDDEATH or _PULSE_CODE_THREADDEATH * from the kernel? */ // break; // } // continue; // } /* name_open() sends a connect message, must EOK this */ // if (msg.hdr.type == _IO_CONNECT ) { // MsgReply( rcvid, EOK, NULL, 0 ); // continue; // } /* Some other QNX IO message was received; reject it */ // if (msg.hdr.type > _IO_BASE && msg.hdr.type <= _IO_MAX ) { // MsgError( rcvid, ENOSYS ); // continue; // } /* A message (presumable ours) received, handle */ printf("Server receive text :%s \n", msg.text); //czyszcze rmsg.text przed ponownym urzyciem memset(&rmsg.text[0], 0, sizeof(rmsg.text)); rmsg.from = getpid(); rmsg.typ = 1; rmsg.ile = 0;//tu modyf int i = 0; // for(i = 0; i < strlen(msg.text); i++) // rmsg.text[i] = msg.text[i]; char letter ; for(i = 0; i < strlen(msg.text); i++){ //if(islower(msg.text[i]) ){ letter = toupper(msg.text[i]); // rmsg.text[i] = letter;//844 rmsg.text[i] = letter; //msg.text[i]; //} //} } printf("server will send text : %s\n", rmsg.text); //rmsg.text[1] = 's'; MsgReply(rcvid, EOK, &rmsg, sizeof(rmsg)); } /* Remove the name from the space */ name_detach(attach, 0); return EXIT_SUCCESS; }
/**************************************************************************** * * Subroutine main * *****************************************************************************/ int main(int argc, char *argv[]) { int tlkilled,tlpid, rc,status; /*tlpid=trace logger pid */ struct traceparser_state * tp_state; char message[200]; pthread_t cur_thread; /* * Start the tests. */ teststart(argv[0]); /* Get rid of tracelogger if it is running */ tlkilled=kill_tl(); /* Setup a channel for the MsgSend Events */ chid=ChannelCreate(0); assert(chid!=-1); /* Setup the barrier used to syncronize */ rc=pthread_barrier_init(&global_barrier, NULL, 2); assert(rc==EOK); /* Setup the mutex for the mutex/condvar state test */ rc=pthread_mutex_init(&mymutex,NULL); assert(rc==EOK); /* Setup the condvar for the condvar state test */ rc=pthread_cond_init(&mycondvar,NULL); assert(rc==EOK); /* setup the sem tfor the sem state test */ rc=sem_init(&mysem, 0,0); assert(rc==0); /* Setup the needed child */ child_pid=fork(); assert(child_pid!=-1); if (child_pid==0) { /* This child is used only in the stopped state test. * it will just sit and loop */ while (1) { delay(10); } exit(0); } /* and create a thread to go into various states */ rc=pthread_create(&cur_thread, NULL, state_thread, NULL); assert(rc==EOK); for (cur_state=STATE_DEAD;cur_state<=STATE_SEM;cur_state++) { /* these states can not be reliably and or safely triggered. */ if ((cur_state==STATE_STACK) || (cur_state==STATE_WAITPAGE) || cur_state==STATE_INTR) continue; /***********************************************************************/ /***********************************************************************/ /* * Make sure that if we trigger a thread state, that it gets logged * properly (all the information in the tracelogger is correct) * This tests the information provided in wide mode. */ snprintf(message, sizeof(message),"%s in wide mode", state_str[cur_state]); testpntbegin(message); exp_thread=cur_thread; /* We need to start up the tracelogger in daemon mode, 1 itteration. * we will filter out everything other then thread states, then * start logging. * We then will trigger a thread state change, and flush the trace buffer. * This should create a VERY minimal trace buffer that will be easily parsed */ tlpid=start_logger(); sleep(1); /* Set the logger to wide emmiting mode */ rc=TraceEvent(_NTO_TRACE_SETALLCLASSESWIDE); assert(rc!=-1); fast_mode=WIDE; /* Add the given thread event in the thread class back in */ rc=TraceEvent(_NTO_TRACE_ADDEVENT, _NTO_TRACE_THREAD,(1<<cur_state)); assert(rc!=-1); /* Filter out all tids other then the state_thread */ if (cur_state==STATE_STOPPED) { rc=TraceEvent(_NTO_TRACE_SETCLASSTID, _NTO_TRACE_THREAD, child_pid, 1); } else { rc=TraceEvent(_NTO_TRACE_SETCLASSTID, _NTO_TRACE_THREAD, getpid(),cur_thread); } assert(rc!=-1); /* then trigger an event. Logging is started inside the state thread * right before it tries to trigger the given state. * the two barrier waits are to * 1) Tell the state thread that everything is setup so it should trigger the event * 2) Wait for the state thread to tell us it has finished. */ pthread_barrier_wait(&global_barrier); if ((cur_state==STATE_SEND)|| (cur_state==STATE_REPLY)) { /* If the thread is going into the send state, we should receive and reply */ sleep(1); status=MsgReceive(chid, message, sizeof(message), NULL); MsgReply(status, EOK, "ok", 3); } else if (cur_state==STATE_RECEIVE) { /* If the thread is going to call reveive, we should send it a message */ sleep(1); status=ConnectAttach(0, getpid(), chid, _NTO_SIDE_CHANNEL, 0); MsgSend(status, message, 10, message,10); } else if (cur_state==STATE_MUTEX) { pthread_mutex_lock(&mymutex); sleep(2); pthread_mutex_unlock(&mymutex); } else if (cur_state==STATE_CONDVAR) { sleep(2); pthread_cond_signal(&mycondvar); } else if (cur_state==STATE_SEM) { sleep(2); sem_post(&mysem); } /* If the state thread is going to try to trigger the dead state, it will have to * exit, so we can not expect it to call barrier_wait to tell us it's done. */ if ((1<<cur_state)!=_NTO_TRACE_THDEAD) { pthread_barrier_wait(&global_barrier); } else { /* If the state thread is going to exit, then we should just * give it time to exit, then restart it. */ sleep(2); rc=pthread_join(cur_thread, (void **)&status); assert(rc==EOK); rc=pthread_create(&cur_thread, NULL, state_thread, NULL); } delay(100); /* flush the trace buffer and wait for the tracelogger to exit*/ rc=TraceEvent(_NTO_TRACE_FLUSHBUFFER); assert(rc!=-1); rc=waitpid(tlpid, &status, 0); assert(tlpid==rc); /* Now, setup the traceparser lib to pull out the thread state events, * and make sure our event shows up */ tp_state=traceparser_init(NULL); assert(tp_state!=NULL); traceparser_cs(tp_state, NULL, parse_cb, _NTO_TRACE_THREAD, (1<<cur_state)); /* Since we don't want a bunch of output being displayed in the * middle of the tests, turn off verbose output. */ traceparser_debug(tp_state, stdout, _TRACEPARSER_DEBUG_NONE); /* Set correct_values to 0, so we can see if the callback actually * got called. */ correct_values=0; /* And parse the tracebuffer */ traceparser(tp_state, NULL, "/dev/shmem/tracebuffer"); if (correct_values==0) testpntfail("Our callback never got called, no events?"); else if (correct_values==-1) testpntfail("Got the wrong thread state"); else if (correct_values==-2) testpntfail("Got the wrong pid"); else if (correct_values==-3) testpntfail("Got the wrong tid"); else if (correct_values==1) testpntpass("Got the correct values"); else testpntfail("This should not happen"); traceparser_destroy(&tp_state); testpntend(); /***********************************************************************/ /***********************************************************************/ /* * Make sure that if we trigger a thread state, that it gets logged * properly (all the information in the tracelogger is correct) * This tests the information provided in fast mode. */ snprintf(message, sizeof(message),"%s in fast mode", state_str[cur_state]); testpntbegin(message); exp_thread=cur_thread; /* We need to start up the tracelogger in daemon mode, 1 itteration. * we will filter out everything other then thread states, then * start logging. * We then will trigger a thread state change, and flush the trace buffer. * This should create a VERY minimal trace buffer that will be easily parsed */ tlpid=start_logger(); sleep(1); /* Set the logger to fast emmiting mode */ rc=TraceEvent(_NTO_TRACE_SETALLCLASSESFAST); assert(rc!=-1); fast_mode=FAST; /* Add the given thread event in the thread class back in */ rc=TraceEvent(_NTO_TRACE_ADDEVENT, _NTO_TRACE_THREAD,(1<<cur_state)); assert(rc!=-1); /* Filter out all tids other then the state_thread */ if (cur_state==STATE_STOPPED) { rc=TraceEvent(_NTO_TRACE_SETCLASSTID, _NTO_TRACE_THREAD, child_pid, 1); } else { rc=TraceEvent(_NTO_TRACE_SETCLASSTID, _NTO_TRACE_THREAD, getpid(),cur_thread); } assert(rc!=-1); /* then trigger an event. Logging is started inside the state thread * right before it tries to trigger the given state. * the two barrier waits are to * 1) Tell the state thread that everything is setup so it should trigger the event * 2) Wait for the state thread to tell us it has finished. */ pthread_barrier_wait(&global_barrier); if ((cur_state==STATE_SEND)|| (cur_state==STATE_REPLY)) { /* If the thread is going into the send state, we should receive and reply */ sleep(1); status=MsgReceive(chid, message, sizeof(message), NULL); MsgReply(status, EOK, "ok", 3); } else if (cur_state==STATE_RECEIVE) { /* If the thread is going to call reveive, we should send it a message */ sleep(1); status=ConnectAttach(0, getpid(), chid, _NTO_SIDE_CHANNEL, 0); MsgSend(status, message, 10, message,10); } else if (cur_state==STATE_MUTEX) { pthread_mutex_lock(&mymutex); sleep(2); pthread_mutex_unlock(&mymutex); } else if (cur_state==STATE_CONDVAR) { sleep(2); pthread_cond_signal(&mycondvar); } else if (cur_state==STATE_SEM) { sleep(2); sem_post(&mysem); } /* If the state thread is going to try to trigger the dead state, it will have to * exit, so we can not expect it to call barrier_wait to tell us it's done. */ if ((1<<cur_state)!=_NTO_TRACE_THDEAD) { pthread_barrier_wait(&global_barrier); } else { /* If the state thread is going to exit, then we should just * give it time to exit, then restart it. */ sleep(2); rc=pthread_join(cur_thread, (void **)&status); assert(rc==EOK); rc=pthread_create(&cur_thread, NULL, state_thread, NULL); } delay(100); /* flush the trace buffer and wait for the tracelogger to exit*/ rc=TraceEvent(_NTO_TRACE_FLUSHBUFFER); assert(rc!=-1); rc=waitpid(tlpid, &status, 0); assert(tlpid==rc); /* Now, setup the traceparser lib to pull out the thread state events, * and make sure our event shows up */ tp_state=traceparser_init(NULL); assert(tp_state!=NULL); traceparser_cs(tp_state, NULL, parse_cb, _NTO_TRACE_THREAD, (1<<cur_state)); /* Since we don't want a bunch of output being displayed in the * middle of the tests, turn off verbose output. */ traceparser_debug(tp_state, stdout, _TRACEPARSER_DEBUG_NONE); /* Set correct_values to 0, so we can see if the callback actually * got called. */ correct_values=0; /* And parse the tracebuffer */ traceparser(tp_state, NULL, "/dev/shmem/tracebuffer"); if (correct_values==0) testpntfail("Our callback never got called, no events?"); else if (correct_values==-1) testpntfail("Got the wrong thread state"); else if (correct_values==-2) testpntfail("Got the wrong pid"); else if (correct_values==-3) testpntfail("Got the wrong tid"); else if (correct_values==1) testpntpass("Got the correct values"); else testpntfail("This should not happen"); traceparser_destroy(&tp_state); testpntend(); /***********************************************************************/ } /* If the tracelogger was running when we started, we should restart it again */ if (tlkilled==1) system("reopen /dev/null ; tracelogger -n 0 -f /dev/null &"); /* Kill off the child we had forked earler */ kill (child_pid, SIGKILL); teststop(argv[0]); return 0; }
/**************************************************************************** * * Subroutine state_thread * * Purpose: This is a thread that is used to trigger the various thread * states * * Parameters: None * * Returns: Nothing * * *****************************************************************************/ void * state_thread(void * arg) { int rc,x,coid; sigset_t myset; uint64_t timeout; struct sigevent myevent; pthread_t mythread; char buf[100]; while(1) { /* Syncronize with the main thread. */ pthread_barrier_wait(&global_barrier); switch (cur_state) { case STATE_DEAD: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger the dead state by calling pthread_exit */ pthread_exit(NULL); /* Should never get here */ abort(); case STATE_READY: exit_now=0; for (x=0;x<_syspage_ptr->num_cpu;x++) pthread_create(NULL, NULL, ready_thread, NULL); /* Let the new threads get started */ sleep(1); case STATE_RUNNING: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger the running state by just doing some work. * this should also trigger a ready state before * we are running */ x=0; while(x<10) x++; exit_now=1; while(x<1000) x++; exit_now=1; /* and unblock the parent */ pthread_barrier_wait(&global_barrier); break; case STATE_STOPPED: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(100); kill (child_pid, SIGSTOP); delay(10); kill (child_pid, SIGCONT); delay(100); pthread_barrier_wait(&global_barrier); break; case STATE_SEND: case STATE_REPLY: coid=ConnectAttach(0, getpid(), chid, _NTO_SIDE_CHANNEL, 0); /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger the SEND/REPLY blocked states */ MsgSend(coid, buf, 10, buf,10); pthread_barrier_wait(&global_barrier); break; case STATE_RECEIVE: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger a receive state */ rc=MsgReceive(chid, buf, sizeof(buf), NULL); MsgReply(rc, EOK, "ok", 3); pthread_barrier_wait(&global_barrier); break; case STATE_WAITTHREAD: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger a waitthread state */ pthread_create(NULL, NULL, nothing_thread, NULL); pthread_barrier_wait(&global_barrier); break; case STATE_SIGSUSPEND: memset(&myevent, 0, sizeof(myevent)); myevent.sigev_notify = SIGEV_UNBLOCK; timeout = 1*1000000000L; sigemptyset(&myset); sigaddset(&myset, SIGHUP); sigaddset(&myset, SIGBUS); sigaddset(&myset, SIGSEGV); sigaddset(&myset, SIGXCPU); sigaddset(&myset, SIGRTMIN); sigaddset(&myset, SIGRTMAX); /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); TimerTimeout( CLOCK_REALTIME, _NTO_TIMEOUT_SIGSUSPEND,&myevent, &timeout, NULL ); SignalSuspend(&myset); pthread_barrier_wait(&global_barrier); break; case STATE_SIGWAITINFO: memset(&myevent, 0, sizeof(myevent)); myevent.sigev_notify = SIGEV_UNBLOCK; timeout = 1*1000000000L; sigemptyset(&myset); sigaddset(&myset, SIGHUP); sigaddset(&myset, SIGBUS); sigaddset(&myset, SIGSEGV); sigaddset(&myset, SIGXCPU); sigaddset(&myset, SIGRTMIN); sigaddset(&myset, SIGRTMAX); /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); TimerTimeout( CLOCK_REALTIME, _NTO_TIMEOUT_SIGWAITINFO,&myevent, &timeout, NULL ); SignalWaitinfo(&myset,NULL); pthread_barrier_wait(&global_barrier); break; case STATE_NANOSLEEP: /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); sleep(1); sleep(1); pthread_barrier_wait(&global_barrier); break; case STATE_MUTEX: /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); sleep(1); pthread_mutex_lock(&mymutex); pthread_mutex_unlock(&mymutex); pthread_barrier_wait(&global_barrier); break; case STATE_CONDVAR: /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); sleep(1); pthread_mutex_lock(&mymutex); pthread_cond_wait(&mycondvar, &mymutex); pthread_mutex_unlock(&mymutex); pthread_barrier_wait(&global_barrier); break; case STATE_JOIN: pthread_create(&mythread, NULL, nothing_thread, NULL); /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); pthread_join(mythread, NULL); pthread_barrier_wait(&global_barrier); break; case STATE_SEM: /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); sleep(1); sem_wait(&mysem); pthread_barrier_wait(&global_barrier); break; } } }
int main(void) { int rcvid; name_attach_t* attach; msg_buf_t msg; int status; int checksum; struct _msg_info msg_info; listNode_t* list_ptr = NULL; setvbuf (stdout, NULL, _IOLBF, 0); attach = name_attach(NULL, "cksum", 0); if(attach == NULL) { //was there an error creating the channel? perror("name_attach"); //look up the errno code and print exit(EXIT_FAILURE); } while(1) { printf("Waiting for a message...\n"); rcvid = MsgReceive(attach->chid, &msg, sizeof(msg), &msg_info); //PUT CODE HERE to receive msg from client if(rcvid == -1) { //was there an error receiving msg? perror("MsgReceive"); //look up errno code and print break; //try receiving another msg } else if(rcvid > 0) { //msg switch(msg.cksum.msg_type) { case _IO_CONNECT: //name_open() within the client may send this MsgReply(rcvid, EOK, NULL, 0); break; case CKSUM_MSG_TYPE: printf("Message received, client scoid = %d\n", msg_info.scoid); list_ptr = add_client_to_list(list_ptr, msg_info.scoid); print_list(list_ptr); checksum = calculate_checksum(msg.cksum.string_to_cksum); status = MsgReply(rcvid, EOK, &checksum, sizeof(checksum) ); if(-1 == status) { perror("MsgReply"); } break; default: MsgReply(rcvid, ENOSYS, NULL, 0); break; } } else if(rcvid == 0) { //message switch(msg.pulse.code) { case _PULSE_CODE_DISCONNECT: printf("received disconnect pulse from client, scoid = %d\n", msg.pulse.scoid); // list_ptr = remove_client_from_list(list_ptr, msg.pulse.scoid); // if(retp == list_ptr) { // printf("can't find client %d in list\n", msg.pulse.scoid); // } // ConnectDetach(msg.pulse.scoid); print_list(list_ptr); break; default: printf("unknown pulse received, code = %d\n", msg.pulse.code); } } else { printf("received unexpected msg with rcvid < -1 !!!\n"); } } return 0; }
static int shm_msg(resmgr_context_t *ctp, io_msg_t *pmsg, RESMGR_OCB_T *ocb) { union { io_msg_t hdr; shmmgr_get_t get; shmmgr_attach_t attach; shmmgr_detach_t detach; shmmgr_ctl_t ctl; } *msg = (void *)pmsg; struct shmid_ds_pool *sd; struct _client_info info; char buf[128]; int status; if (msg->hdr.i.mgrid != _IOMGR_SHMMGR) { return _RESMGR_DEFAULT; } // we will always need the client info if ((status = ConnectClientInfo_r(ctp->info.scoid, &info, NGROUPS_MAX)) != EOK) { return status; } switch (msg->hdr.i.subtype) { case _SHMMGR_GET: return msg_get(ctp, &msg->get, &info); case _SHMMGR_ATTACH: case _SHMMGR_DETACH: if (msg->attach.i.shmid < 0 || msg->attach.i.shmid >= shmid_array_total) { return EINVAL; } _mutex_lock(&shmid_array_mutex); sd = &shmid_array[msg->attach.i.shmid]; if (sd->shmds.shm_perm.mode & SHMSEG_FREE) { _mutex_unlock(&shmid_array_mutex); return EINVAL; } if ((status = ipcperm(&info, &sd->shmds.shm_perm, (msg->attach.i.flag & SHM_RDONLY) ? IPC_R : IPC_R | IPC_W)) != 0) { _mutex_unlock(&shmid_array_mutex); return status; } sd->shmds.shm_lpid = info.pid; sd->shmds.shm_atime = time(NULL); if (msg->hdr.i.subtype == _SHMMGR_ATTACH) sd->shmds.shm_nattch++; else sd->shmds.shm_nattch--; msg->attach.o.size = sd->shmds.shm_segsz; _mutex_unlock(&shmid_array_mutex); MsgReply(ctp->rcvid, EOK, &msg->attach.o, sizeof(msg->attach.o)); break; case _SHMMGR_CTL: if (msg->ctl.i.shmid < 0 || msg->ctl.i.shmid >= shmid_array_total) { return EINVAL; } _mutex_lock(&shmid_array_mutex); sd = &shmid_array[msg->ctl.i.shmid]; if (sd->shmds.shm_perm.mode & SHMSEG_FREE) { _mutex_unlock(&shmid_array_mutex); return EINVAL; } switch(msg->ctl.i.cmd) { case IPC_STAT: if ((status = ipcperm(&info, &sd->shmds.shm_perm, IPC_R)) != 0) { _mutex_unlock(&shmid_array_mutex); return status; } memcpy(&msg->ctl.i.buf, &sd->shmds, sizeof(sd->shmds)); break; case IPC_SET: if ((status = ipcperm(&info, &sd->shmds.shm_perm, IPC_M)) != 0) { _mutex_unlock(&shmid_array_mutex); return status; } sd->shmds.shm_perm.uid = msg->ctl.i.buf.shm_perm.uid; sd->shmds.shm_perm.gid = msg->ctl.i.buf.shm_perm.gid; sd->shmds.shm_perm.mode = (msg->ctl.i.buf.shm_perm.mode & S_IPERMS) | (sd->shmds.shm_perm.mode & ~S_IPERMS); sd->shmds.shm_ctime = time(NULL); break; case IPC_RMID: if ((status = ipcperm(&info, &sd->shmds.shm_perm, IPC_M)) != 0) { _mutex_unlock(&shmid_array_mutex); return status; } snprintf(buf, sizeof(buf), "%s/%d", PATH_SHM, msg->ctl.i.shmid); shm_unlink(buf); sd->shmds.shm_perm.mode = SHMSEG_FREE; break; } _mutex_unlock(&shmid_array_mutex); MsgReply(ctp->rcvid, EOK, &msg->ctl.o, sizeof(msg->ctl.o)); } return _RESMGR_NOREPLY; }
static int msg_get(resmgr_context_t *ctp, shmmgr_get_t *msgget, struct _client_info *info) { struct shmid_ds_pool *sd; int i, error, fd, spare; char buf[128]; spare = -1; sd = NULL; _mutex_lock(&shmid_array_mutex); if (msgget->i.key != IPC_PRIVATE) { /* see if the key related to a shmid already */ for (i = 0; i < shmid_array_total; i++) { sd = &shmid_array[i]; if (sd->shmds.shm_perm.mode & SHMSEG_FREE) { if (spare == -1) spare = i; continue; } if (sd->key == msgget->i.key) break; } if (i == shmid_array_total) { sd = NULL; } if (sd != NULL) { /* if the key already exists */ if ((error = ipcperm(info, &sd->shmds.shm_perm, msgget->i.flag & S_IPERMS)) != 0) { _mutex_unlock(&shmid_array_mutex); return error; } if (msgget->i.size && msgget->i.size > sd->shmds.shm_segsz) { _mutex_unlock(&shmid_array_mutex); return EINVAL; } if ((msgget->i.flag & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL)) { _mutex_unlock(&shmid_array_mutex); return EEXIST; } msgget->o.key = msgget->i.key; msgget->o.shmid = i; _mutex_unlock(&shmid_array_mutex); MsgReply(ctp->rcvid, EOK, &msgget->o, sizeof(msgget->o)); return _RESMGR_NOREPLY; } else { // no sd associated with the key, we need an IPC_CREAT if ((msgget->i.flag & IPC_CREAT) == 0) { _mutex_unlock(&shmid_array_mutex); return ENOENT; } } } /* find a spare sd (we still have the mutex) */ if (spare == -1) { for (i = 0; i < shmid_array_total; i++) { sd = &shmid_array[i]; if (sd->shmds.shm_perm.mode & SHMSEG_FREE) { spare = i; break; } } if (i == shmid_array_total) { sd = NULL; sd = realloc(shmid_array, (shmid_array_total + SHMID_ARRAY_GROW) * sizeof(*sd)); if (sd == NULL) { _mutex_unlock(&shmid_array_mutex); return errno; } for (i = shmid_array_total; i < shmid_array_total + SHMID_ARRAY_GROW; i++) { sd[i].shmds.shm_perm.mode |= SHMSEG_FREE; } i = shmid_array_total; shmid_array = sd; shmid_array_total += SHMID_ARRAY_GROW; } } else { i = spare; } sd = &shmid_array[i]; memset(sd, 0, sizeof(*sd)); sd->shmds.shm_perm.mode = (msgget->i.flag & S_IPERMS) | SHMSEG_ALLOCATED; _mutex_unlock(&shmid_array_mutex); snprintf(buf, sizeof(buf), "%s/%d", PATH_SHM, i); #if 0 if ((fd = shm_open(buf, O_CREAT, (msgget->i.flag & S_IPERMS))) == -1 || ftruncate(fd, msgget->i.size) == -1 ) { goto fail; } #else if ((fd = shm_open(buf, O_CREAT | O_RDWR, (msgget->i.flag & S_IPERMS))) == -1) { goto fail; } if (fchown(fd, info->cred.euid, info->cred.egid) == -1 || ftruncate(fd, msgget->i.size) == -1 ) { close(fd); shm_unlink(buf); goto fail; } #endif close(fd); /* set up the sd */ sd->shmds.shm_perm.cuid = info->cred.euid; sd->shmds.shm_perm.cgid = info->cred.egid; sd->shmds.shm_perm.uid = info->cred.ruid; sd->shmds.shm_perm.gid = info->cred.rgid; sd->shmds.shm_segsz = msgget->i.size; sd->shmds.shm_cpid = info->pid; sd->shmds.shm_ctime = time(NULL); sd->key = msgget->i.key; /* reply to let client know the shmid */ msgget->o.key = msgget->i.key; msgget->o.shmid = i; MsgReply(ctp->rcvid, EOK, &msgget->o, sizeof(msgget->o)); return _RESMGR_NOREPLY; fail: _mutex_lock(&shmid_array_mutex); sd->shmds.shm_perm.mode = SHMSEG_FREE; _mutex_unlock(&shmid_array_mutex); return errno; }
int main(int argc, char *argv[]) { name_attach_t *att; int rcvid; struct _msg_info msg_info; struct sigevent sigev; int self_coid; int achid; struct _asyncmsg_get_header *agh, *agh1; /* register my name so client can find me */ att = name_attach(NULL,RECV_NAME, 0 ); if (NULL == att ) { perror(PROGNAME "name_attach()"); exit(EXIT_FAILURE); } /* create a connection to the synchronous channel created by the * name_attach() call. Will use this to specify where the pulses * flagging async data available should be delivered. */ self_coid = ConnectAttach( 0, 0, att->chid, _NTO_SIDE_CHANNEL, 0 ); if( -1 == self_coid ) { perror(PROGNAME "ConnectAttach"); exit( EXIT_FAILURE ); } /* and fill in the event structure to describe a priority 10 pulse * to be delivered to my synchronous channel */ SIGEV_PULSE_INIT( &sigev, self_coid, 10, PULSE_ASYNCH_EVENT, 0 ); /* create an asynchrounous channel with automatic buffering * it will not block an asyncmsg_get() call if there are no messages available * it will receive up to 10 messages of up to 1024 bytes each at once * It will get a pulse notification when the queue of available messages goes * from empty to non-empty */ achid = asyncmsg_channel_create( _NTO_CHF_ASYNC_NONBLOCK, 0666, 1024, 10, &sigev, NULL ); if( -1 == achid ) { perror( "asyncmsg_channel_create"); exit( EXIT_FAILURE ); } while(1) { rcvid = MsgReceive( att->chid, &recv_buf, sizeof (recv_buf), &msg_info ); if( -1 == rcvid ) { perror(PROGNAME "MsgReceive failed"); continue; } if ( 0 == rcvid ) { /* we received a pulse */ printf("got a pulse\n"); switch( recv_buf.pulse.code ) { /* system disconnect pulse */ case _PULSE_CODE_DISCONNECT: ConnectDetach( recv_buf.pulse.scoid ); printf(PROGNAME "disconnect from a client %X\n", recv_buf.pulse.scoid); break; /* our pulse - we've got one or more messages */ case PULSE_ASYNCH_EVENT: /* get one or more messages from our channel */ agh = asyncmsg_get( achid ); if (NULL == agh ) { perror("went to get a message, but nothing was there"); } else { /* the async receive header is, actually, a linked list of headers * if multiple messages have been received at once, so we need to * walk the list, looking at each header and message in turn */ while( agh ) { printf("the message came from %d in %d parts\n", agh->info.pid, agh->parts); printf("the data is '%s'\n", (char *)(agh->iov->iov_base)); agh1 = agh; agh = agh1->next; /* free this message */ asyncmsg_free( agh1 ); } } break; default: printf(PROGNAME "unexpect pulse code: %d\n", recv_buf.pulse.code ); break; } continue; } /* not an error, not a pulse, therefor a message */ if ( recv_buf.type == _IO_CONNECT ) { /* _IO_CONNECT because someone did a name_open() to us, must EOK it.*/ MsgReply( rcvid, EOK, NULL, 0 ); continue; } if ( recv_buf.type > _IO_BASE && recv_buf.type <= _IO_MAX ) { /* unexpected system message,probably qconn, error it */ MsgError( rcvid, ENOSYS ); continue; } switch( recv_buf.type ) { /* here our client asked for our asynchronous channel id * reply with it */ case GET_ACHID: printf("got request for my achid\n"); MsgReply(rcvid, 0, &achid, sizeof(achid )); break; default: /* some other unexpect message */ printf(PROGNAME "unexpect message type: %d\n", recv_buf.type); MsgError(rcvid, ENOSYS ); break; } } }