static void send_message_to_process(endpoint_t who, int ret, int ignore) { message m; m.m_type = ret; ipc_sendnb(who, &m); }
/*===========================================================================* * reply * *===========================================================================*/ static void reply(message *m_out, endpoint_t whom, int result) { /* Send a reply to a user process. If the send fails, just ignore it. */ int r; m_out->m_type = result; r = ipc_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(); } }
/*===========================================================================* * send_reply * *===========================================================================*/ static void send_reply(endpoint_t endpt, message *m_ptr, int ipc_status) { /* Send a reply message to a request. */ int r; /* 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 = ipc_sendnb(endpt, m_ptr); else r = asynsend3(endpt, m_ptr, AMF_NOREPLY); if (r != OK) printf("blockdriver: unable to send reply to %d: %d\n", endpt, r); }
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.m_lc_readclock_rtcdev.flags); if (reply_status != OK) { break; } /* write results back to calling process */ reply_status = store_t(caller, m.m_lc_readclock_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, m.m_lc_readclock_rtcdev.tm, &t); if (reply_status != OK) { break; } reply_status = rtc.set_time(&t, m.m_lc_readclock_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.m_readclock_lc_rtcdev.status = reply_status; log_debug(&log, "Sending Reply"); r = ipc_sendnb(caller, &m); if (r != OK) { log_warn(&log, "ipc_sendnb() failed\n"); continue; } } rtc.exit(); return 0; }
/*===========================================================================* * do_semop * *===========================================================================*/ 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->m_lc_ipc_semop.id; nsops = m->m_lc_ipc_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->m_lc_ipc_semop.ops, SELF, (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 >= 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; ipc_sendnb(who_e, m); } /* awaken process if possible */ update_semaphores(); return 0; }
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.m_lc_readclock_rtcdev.flags); if (reply_status != OK) { break; } /* write results back to calling process */ reply_status = store_t(caller, m.m_lc_readclock_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, m.m_lc_readclock_rtcdev.grant, &t); if (reply_status != OK) { break; } reply_status = rtc_set_time(&t, m.m_lc_readclock_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.m_readclock_lc_rtcdev.status = reply_status; log_debug(&log, "Sending Reply"); r = ipc_sendnb(caller, &m); if (r != OK) { log_warn(&log, "ipc_sendnb() failed\n"); continue; } } rtc_exit(); return 0; }