PRIVATE void send_message_to_process(endpoint_t who, int ret, int ignore) { message m; m.m_type = ret; sendnb(who, &m); }
/*===========================================================================* * blockdriver_reply * *===========================================================================*/ void blockdriver_reply(message *m_ptr, int ipc_status, int reply) { /* Reply to a block request sent to the driver. */ endpoint_t caller_e; long id; int r; if (reply == EDONTREPLY) return; caller_e = m_ptr->m_source; id = m_ptr->BDEV_ID; memset(m_ptr, 0, sizeof(*m_ptr)); m_ptr->m_type = BDEV_REPLY; m_ptr->BDEV_STATUS = reply; m_ptr->BDEV_ID = id; /* If we would block sending the message, send it asynchronously. The NOREPLY * flag is set because the caller may also issue a SENDREC (mixing sync and * async comm), and the asynchronous reply could otherwise end up satisfying * the SENDREC's receive part, after which our next SENDNB call would fail. */ if (IPC_STATUS_CALL(ipc_status) == SENDREC) r = sendnb(caller_e, m_ptr); else r = asynsend3(caller_e, m_ptr, AMF_NOREPLY); if (r != OK) printf("blockdriver_reply: unable to send reply to %d: %d\n", caller_e, r); }
// up not synchronous void sem_up(endpoint_t e) { message m; int r; m.m_type = SEM_UP; r = sendnb(e, &m); if (r) printf("semaphore up error\n"); }
/*===========================================================================* * reply * *===========================================================================*/ void reply(endpoint_t whom, int result) { /* Send a reply to a user process. If the send fails, just ignore it. */ int r; m_out.reply_type = result; r = sendnb(whom, &m_out); if (r != OK) { printf("VFS: %d couldn't send reply %d to %d: %d\n", mthread_self(), result, whom, r); util_stacktrace(); } }
/*===========================================================================* * sync_reply * *===========================================================================*/ static void sync_reply(message *m_ptr, int ipc_status, int reply) { /* Reply to a message sent to the driver. */ endpoint_t caller_e, user_e; int r; caller_e = m_ptr->m_source; user_e = m_ptr->USER_ENDPT; m_ptr->m_type = TASK_REPLY; m_ptr->REP_ENDPT = user_e; m_ptr->REP_STATUS = reply; /* If we would block sending the message, send it asynchronously. */ if (IPC_STATUS_CALL(ipc_status) == SENDREC) r = sendnb(caller_e, m_ptr); else r = asynsend(caller_e, m_ptr); if (r != OK) printf("driver_reply: unable to send reply to %d: %d\n", caller_e, r); }
int main(int argc, char *argv[]) { int r, i; struct tm t; endpoint_t user, caller; message m; int ipc_status, reply_status; env_setargs(argc, argv); r = i2cdriver_env_parse(&bus, &addresses[0], valid_addrs); if (r < 0) { log_warn(&log, "Expecting -args 'bus=X address=0xYY'\n"); log_warn(&log, "Example -args 'bus=1 address=0x48'\n"); return EXIT_FAILURE; } else if (r > 0) { log_warn(&log, "Invalid slave address for device, expecting 0x48\n"); return EXIT_FAILURE; } sef_local_startup(); while (TRUE) { /* Receive Message */ r = sef_receive_status(ANY, &m, &ipc_status); if (r != OK) { log_warn(&log, "sef_receive_status() failed\n"); continue; } if (is_ipc_notify(ipc_status)) { if (m.m_source == DS_PROC_NR) { for (i = 0; i < NADDRESSES; i++) { /* changed state, update endpoint */ i2cdriver_handle_bus_update (&bus_endpoint, bus, addresses[i]); } } /* Do not reply to notifications. */ continue; } caller = m.m_source; log_debug(&log, "Got message 0x%x from 0x%x\n", m.m_type, caller); switch (m.m_type) { case RTCDEV_GET_TIME_G: /* Any user can read the time */ reply_status = rtc_get_time(&t, m.RTCDEV_FLAGS); if (reply_status != OK) { break; } /* write results back to calling process */ reply_status = store_t(caller, (cp_grant_id_t) m.RTCDEV_GRANT, &t); break; case RTCDEV_SET_TIME_G: /* Only super user is allowed to set the time */ if (getnuid(caller) == SUPER_USER) { /* read time from calling process */ reply_status = fetch_t(caller, (cp_grant_id_t) m.RTCDEV_GRANT, &t); if (reply_status != OK) { break; } reply_status = rtc_set_time(&t, m.RTCDEV_FLAGS); } else { reply_status = EPERM; } break; case RTCDEV_PWR_OFF: reply_status = ENOSYS; break; default: /* Unrecognized call */ reply_status = EINVAL; break; } /* Send Reply */ m.m_type = RTCDEV_REPLY; m.RTCDEV_STATUS = reply_status; log_debug(&log, "Sending Reply"); r = sendnb(caller, &m); if (r != OK) { log_warn(&log, "sendnb() failed\n"); continue; } } rtc_exit(); return 0; }
PUBLIC int main(int argc, char *argv[]) { message m; /* SEF local startup. */ env_setargs(argc, argv); sef_local_startup(); while (TRUE) { int r; int i; if ((r = sef_receive(ANY, &m)) != OK) printf("sef_receive failed %d.\n", r); who_e = m.m_source; call_type = m.m_type; if(verbose) printf("IPC: get %d from %d\n", call_type, who_e); if (call_type & NOTIFY_MESSAGE) { switch (who_e) { case PM_PROC_NR: /* PM sends a notify() on shutdown, * checkout if there are still IPC keys, * give warning messages. */ if (!is_sem_nil() || !is_shm_nil()) printf("IPC: exit with un-clean states.\n"); break; case VM_PROC_NR: /* currently, only semaphore needs such information. */ sem_process_vm_notify(); break; default: printf("IPC: ignoring notify() from %d\n", who_e); break; } continue; } /* dispatch messages */ for (i = 0; i < SIZE(ipc_calls); i++) { if (ipc_calls[i].type == call_type) { int result; result = ipc_calls[i].func(&m); if (ipc_calls[i].reply) break; m.m_type = result; if(verbose && result != OK) printf("IPC: error for %d: %d\n", call_type, result); if ((r = sendnb(who_e, &m)) != OK) printf("IPC send error %d.\n", r); break; } } if (i == SIZE(ipc_calls)) { /* warn and then ignore */ printf("IPC unknown call type: %d from %d.\n", call_type, who_e); } update_refcount_and_destroy(); } /* no way to get here */ return -1; }
/*===========================================================================* * do_semop * *===========================================================================*/ PUBLIC int do_semop(message *m) { int id, i, j, r; struct sembuf *sops; unsigned int nsops; struct sem_struct *sem; int no_reply = 0; id = m->SEMOP_ID; nsops = (unsigned int) m->SEMOP_SIZE; r = EINVAL; if (!(sem = sem_find_id(id))) goto out; if (nsops <= 0) goto out; r = E2BIG; if (nsops > SEMOPM) goto out; /* check for read permission */ r = EACCES; if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0444)) goto out; /* get the array from user application */ r = ENOMEM; sops = malloc(sizeof(struct sembuf) * nsops); if (!sops) goto out_free; r = sys_datacopy(who_e, (vir_bytes) m->SEMOP_OPS, SELF_E, (vir_bytes) sops, sizeof(struct sembuf) * nsops); if (r != OK) { r = EINVAL; goto out_free; } #ifdef DEBUG_SEM for (i = 0; i < nsops; i++) printf("SEMOP: num:%d op:%d flg:%d\n", sops[i].sem_num, sops[i].sem_op, sops[i].sem_flg); #endif /* check for value range */ r = EFBIG; for (i = 0; i < nsops; i++) if (sops[i].sem_num < 0 || sops[i].sem_num >= sem->semid_ds.sem_nsems) goto out_free; /* check for duplicate number */ r = EINVAL; for (i = 0; i < nsops; i++) for (j = i + 1; j < nsops; j++) if (sops[i].sem_num == sops[j].sem_num) goto out_free; /* check for EAGAIN error */ r = EAGAIN; for (i = 0; i < nsops; i++) { int op_n, val; op_n = sops[i].sem_op; val = sem->sems[sops[i].sem_num].semval; if ((sops[i].sem_flg & IPC_NOWAIT) && ((!op_n && val) || (op_n < 0 && -op_n > val))) goto out_free; } /* there will be no errors left, so we can go ahead */ for (i = 0; i < nsops; i++) { struct semaphore *s; int op_n; s = &sem->sems[sops[i].sem_num]; op_n = sops[i].sem_op; s->sempid = getnpid(who_e); if (op_n > 0) { /* check for alter permission */ r = EACCES; if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222)) goto out_free; s->semval += sops[i].sem_op; } else if (!op_n) { if (s->semval) { /* put the process asleep */ s->semzcnt++; s->zlist = realloc(s->zlist, sizeof(struct waiting) * s->semzcnt); if (!s->zlist) { printf("IPC: zero waiting list lost...\n"); break; } s->zlist[s->semzcnt-1].who = who_e; s->zlist[s->semzcnt-1].val = op_n; #ifdef DEBUG_SEM printf("SEMOP: Put into sleep... %d\n", who_e); #endif no_reply++; } } else { /* check for alter permission */ r = EACCES; if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222)) goto out_free; if (s->semval >= -op_n) s->semval += op_n; else { /* put the process asleep */ s->semncnt++; s->nlist = realloc(s->nlist, sizeof(struct waiting) * s->semncnt); if (!s->nlist) { printf("IPC: increase waiting list lost...\n"); break; } s->nlist[s->semncnt-1].who = who_e; s->nlist[s->semncnt-1].val = -op_n; no_reply++; } } } r = OK; out_free: free(sops); out: /* if we reach here by errors * or with no errors but we should reply back. */ if (r != OK || !no_reply) { m->m_type = r; sendnb(who_e, m); } /* awaken process if possible */ update_semaphores(); return 0; }
int main(int argc, char *argv[]) { int r; endpoint_t user, caller; message m; int ipc_status; env_setargs(argc, argv); r = i2cdriver_env_parse(&bus, &address, valid_addrs); if (r < 0) { log_warn(&log, "Expecting -args 'bus=X address=0xYY'\n"); log_warn(&log, "Example -args 'bus=1 address=0x24'\n"); return EXIT_FAILURE; } else if (r > 0) { log_warn(&log, "Invalid slave address for device, expecting 0x24\n"); return EXIT_FAILURE; } sef_local_startup(); while (TRUE) { /* Receive Message */ r = sef_receive_status(ANY, &m, &ipc_status); if (r != OK) { log_warn(&log, "sef_receive_status() failed\n"); continue; } log_trace(&log, "Got a message 0x%x from 0x%x\n", m.m_type, m.m_source); if (is_ipc_notify(ipc_status)) { switch (m.m_source) { case DS_PROC_NR: /* bus driver changed state, update endpoint */ i2cdriver_handle_bus_update(&bus_endpoint, bus, address); break; case HARDWARE: intr_handler(); break; default: break; } /* Do not reply to notifications. */ continue; } caller = m.m_source; user = m.USER_ENDPT; /* * Handle Message * * So far this driver only deals with notifications * so it always replies to non-notifications with EINVAL. */ /* Send Reply */ m.m_type = TASK_REPLY; m.REP_ENDPT = user; m.REP_STATUS = EINVAL; r = sendnb(caller, &m); if (r != OK) { log_warn(&log, "sendnb() failed\n"); continue; } } return 0; }
PUBLIC int main(int argc, char *argv[]) { message m; /* SEF local startup. */ env_setargs(argc, argv); sef_local_startup(); while (TRUE) { int r; int i; if ((r = sef_receive(ANY, &m)) != OK) printf("sef_receive failed %d.\n", r); who_e = m.m_source; call_type = m.m_type; if(verbose) printf("IPC: get %d from %d\n", call_type, who_e); if (call_type & NOTIFY_MESSAGE) { switch (who_e) { case VM_PROC_NR: /* currently, only semaphore needs such information. */ sem_process_vm_notify(); break; default: printf("IPC: ignoring notify() from %d\n", who_e); break; } continue; } /* dispatch messages */ for (i = 0; i < SIZE(ipc_calls); i++) { /* If any process does an IPC call, * we have to know about it exiting. * Tell VM to watch it for us. */ if(vm_watch_exit(m.m_source) != OK) { printf("IPC: watch failed on %d\n", m.m_source); } if (ipc_calls[i].type == call_type) { int result; result = ipc_calls[i].func(&m); if (ipc_calls[i].reply) break; m.m_type = result; if(verbose && result != OK) printf("IPC: error for %d: %d\n", call_type, result); if ((r = sendnb(who_e, &m)) != OK) printf("IPC send error %d.\n", r); break; } } if (i == SIZE(ipc_calls)) { /* warn and then ignore */ printf("IPC unknown call type: %d from %d.\n", call_type, who_e); } update_refcount_and_destroy(); } /* no way to get here */ return -1; }
int main(int argc, char **argv) { int r; endpoint_t caller; struct tm t; message m; int ipc_status, reply_status; env_setargs(argc, argv); sef_local_startup(); while (TRUE) { /* Receive Message */ r = sef_receive_status(ANY, &m, &ipc_status); if (r != OK) { log_warn(&log, "sef_receive_status() failed\n"); continue; } if (is_ipc_notify(ipc_status)) { /* Do not reply to notifications. */ continue; } caller = m.m_source; log_debug(&log, "Got message 0x%x from 0x%x\n", m.m_type, caller); switch (m.m_type) { case RTCDEV_GET_TIME: /* Any user can read the time */ reply_status = rtc.get_time(&t, m.RTCDEV_FLAGS); if (reply_status != OK) { break; } /* write results back to calling process */ reply_status = store_t(caller, (vir_bytes) m.RTCDEV_TM, &t); break; case RTCDEV_SET_TIME: /* Only super user is allowed to set the time */ if (getnuid(caller) == SUPER_USER) { /* read time from calling process */ reply_status = fetch_t(caller, (vir_bytes) m.RTCDEV_TM, &t); if (reply_status != OK) { break; } reply_status = rtc.set_time(&t, m.RTCDEV_FLAGS); } else { reply_status = EPERM; } break; case RTCDEV_PWR_OFF: /* Only PM is allowed to set the power off time */ if (caller == PM_PROC_NR) { reply_status = rtc.pwr_off(); } else { reply_status = EPERM; } break; default: /* Unrecognized call */ reply_status = EINVAL; break; } /* Send Reply */ m.m_type = RTCDEV_REPLY; m.RTCDEV_STATUS = reply_status; log_debug(&log, "Sending Reply"); r = sendnb(caller, &m); if (r != OK) { log_warn(&log, "sendnb() failed\n"); continue; } } rtc.exit(); return 0; }
/*===========================================================================* * main * *===========================================================================*/ PUBLIC int main() { /* Main routine of the process manager. */ int result, s, proc_nr; struct mproc *rmp; sigset_t sigset; pm_init(); /* initialize process manager tables */ /* This is PM's main loop- get work and do it, forever and forever. */ while (TRUE) { get_work(); /* wait for an PM system call */ /* Check for system notifications first. Special cases. */ switch(call_nr) { case SYN_ALARM: pm_expire_timers(m_in.NOTIFY_TIMESTAMP); result = SUSPEND; /* don't reply */ break; case SYS_SIG: /* signals pending */ sigset = m_in.NOTIFY_ARG; if (sigismember(&sigset, SIGKSIG)) { (void) ksig_pending(); } result = SUSPEND; /* don't reply */ break; case PM_GET_WORK: if (who_e == FS_PROC_NR) { send_work(); result= SUSPEND; /* don't reply */ } else result= ENOSYS; break; case PM_EXIT_REPLY: case PM_REBOOT_REPLY: case PM_EXEC_REPLY: case PM_CORE_REPLY: case PM_EXIT_REPLY_TR: if (who_e == FS_PROC_NR) { handle_fs_reply(&m_in); result= SUSPEND; /* don't reply */ } else result= ENOSYS; break; case ALLOCMEM: result= do_allocmem(); break; case FORK_NB: result= do_fork_nb(); break; case EXEC_NEWMEM: result= exec_newmem(); break; case EXEC_RESTART: result= do_execrestart(); break; case PROCSTAT: result= do_procstat(); break; case GETPROCNR: result= do_getprocnr(); break; case GETPUID: result= do_getpuid(); break; case DIAG_REPL : diag_repl(); result= SUSPEND; break; default: /* Else, if the system call number is valid, perform the * call. */ if ((unsigned) call_nr >= NCALLS) { result = ENOSYS; } else { #if ENABLE_SYSCALL_STATS calls_stats[call_nr]++; #endif result = (*call_vec[call_nr])(); } break; } /* Send the results back to the user to indicate completion. */ if (result != SUSPEND) setreply(who_p, result); /* Send out all pending reply messages, including the answer to * the call just made above. */ for (proc_nr=0, rmp=mproc; proc_nr < NR_PROCS; proc_nr++, rmp++) { /* In the meantime, the process may have been killed by a * signal (e.g. if a lethal pending signal was unblocked) * without the PM realizing it. If the slot is no longer in * use or just a zombie, don't try to reply. */ if ((rmp->mp_flags & (REPLY | IN_USE | ZOMBIE)) == (REPLY | IN_USE)) { s=sendnb(rmp->mp_endpoint, &rmp->mp_reply); if (s != OK) { printf("PM can't reply to %d (%s): %d\n", rmp->mp_endpoint, rmp->mp_name, s); } rmp->mp_flags &= ~REPLY; } } } return(OK); }