/*===========================================================================* * start_vtreefs * *===========================================================================*/ PUBLIC void start_vtreefs(struct fs_hooks *hooks, unsigned int nr_inodes, struct inode_stat *stat, index_t nr_indexed_entries) { /* This is the main routine of this service. The main loop consists of * three major activities: getting new work, processing the work, and * sending the reply. The loop exits when the process is signaled to * exit; due to limitations of SEF, it can not return to the caller. */ int call_nr, err, transid; /* Use global variables to work around the inability to pass parameters * through SEF to the initialization function.. */ vtreefs_hooks = hooks; inodes = nr_inodes; root_stat = stat; root_entries = nr_indexed_entries; sef_local_startup(); for (;;) { get_work(); transid = TRNS_GET_ID(fs_m_in.m_type); fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type); if (fs_m_in.m_type == 0) { assert(!IS_VFS_FS_TRANSID(transid)); fs_m_in.m_type = transid; /* Backwards compat. */ transid = 0; } else assert(IS_VFS_FS_TRANSID(transid)); call_nr = fs_m_in.m_type; if (fs_m_in.m_source != VFS_PROC_NR) { if (vtreefs_hooks->message_hook != NULL) { /* If the request is not among the recognized * requests, call the message hook. */ vtreefs_hooks->message_hook(&fs_m_in); } continue; } if (fs_mounted || call_nr == REQ_READSUPER) { call_nr -= VFS_BASE; if (call_nr >= 0 && call_nr < NREQS) { err = (*fs_call_vec[call_nr])(); } else { err = ENOSYS; } } else err = EINVAL; send_reply(err, transid); } }
/*===========================================================================* * main * *===========================================================================*/ int main(void) { /* This is the main program of the file system. The main loop consists of * three major activities: getting new work, processing the work, and sending * the reply. This loop never terminates as long as the file system runs. */ int transid; struct job *job; /* SEF local startup. */ sef_local_startup(); printf("Started VFS: %d worker thread(s)\n", NR_WTHREADS); /* This is the main loop that gets work, processes it, and sends replies. */ while (TRUE) { yield_all(); /* let other threads run */ self = NULL; job = NULL; send_work(); get_work(); transid = TRNS_GET_ID(m_in.m_type); if (IS_VFS_FS_TRANSID(transid)) { job = worker_getjob( (thread_t) transid - VFS_TRANSID); if (job == NULL) { printf("VFS: spurious message %d from endpoint %d\n", m_in.m_type, m_in.m_source); continue; } m_in.m_type = TRNS_DEL_ID(m_in.m_type); } if (job != NULL) { do_fs_reply(job); continue; } else if (who_e == PM_PROC_NR) { /* Calls from PM */ /* Special control messages from PM */ sys_worker_start(do_pm); continue; } else if (is_notify(call_nr)) { /* A task notify()ed us */ sys_worker_start(do_control_msgs); continue; } else if (who_p < 0) { /* i.e., message comes from a task */ /* We're going to ignore this message. Tasks should * send notify()s only. */ printf("VFS: ignoring message from %d (%d)\n", who_e, call_nr); continue; } /* At this point we either have results from an asynchronous device * or a new system call. In both cases a new worker thread has to be * started and there might not be one available from the pool. This is * not a problem (requests/replies are simply queued), except when * they're from an FS endpoint, because these can cause a deadlock. * handle_work() takes care of the details. */ if (IS_DEV_RS(call_nr)) { /* We've got results for a device request */ handle_work(do_async_dev_result); continue; } else { /* Normal syscall. */ handle_work(do_work); } } return(OK); /* shouldn't come here */ }
/*===========================================================================* * main * *===========================================================================*/ PUBLIC int main(int argc, char *argv[]) { /* This is the main routine of this service. The main loop consists of * three major activities: getting new work, processing the work, and * sending the reply. The loop never terminates, unless a panic occurs. */ int ind, transid; message pfs_m_in; message pfs_m_out; /* SEF local startup. */ env_setargs(argc, argv); sef_local_startup(); while(!exitsignaled || busy) { endpoint_t src; /* Wait for request message. */ get_work(&pfs_m_in); transid = TRNS_GET_ID(pfs_m_in.m_type); pfs_m_in.m_type = TRNS_DEL_ID(pfs_m_in.m_type); if (pfs_m_in.m_type == 0) { assert(!IS_VFS_FS_TRANSID(transid)); pfs_m_in.m_type = transid; transid = 0; } else assert(IS_VFS_FS_TRANSID(transid) || transid == 0); src = pfs_m_in.m_source; caller_uid = INVAL_UID; /* To trap errors */ caller_gid = INVAL_GID; req_nr = pfs_m_in.m_type; if (IS_DEV_RQ(req_nr)) { ind = req_nr - DEV_RQ_BASE; if (ind < 0 || ind >= DEV_CALL_VEC_SIZE) { printf("pfs: bad DEV request %d\n", req_nr); pfs_m_out.m_type = EINVAL; } else { (*dev_call_vec[ind])(&pfs_m_in, &pfs_m_out); } } else if (IS_VFS_RQ(req_nr)) { ind = req_nr - VFS_BASE; if (ind < 0 || ind >= FS_CALL_VEC_SIZE) { printf("pfs: bad FS request %d\n", req_nr); pfs_m_out.m_type = EINVAL; } else { pfs_m_out.m_type = (*fs_call_vec[ind])(&pfs_m_in, &pfs_m_out); } } else { printf("pfs: bad request %d\n", req_nr); pfs_m_out.m_type = EINVAL; } if (IS_VFS_RQ(req_nr) && IS_VFS_FS_TRANSID(transid)) { pfs_m_out.m_type = TRNS_ADD_ID(pfs_m_out.m_type, transid); } reply(src, &pfs_m_out); } return(OK); }
/*===========================================================================* * main * *===========================================================================*/ PUBLIC int main(int argc, char *argv[]) { /* This is the main routine of this service. The main loop consists of * three major activities: getting new work, processing the work, and * sending the reply. The loop never terminates, unless a panic occurs. */ int error = OK, ind, transid; unsigned short test_endian = 1; /* SEF local startup. */ env_setargs(argc, argv); sef_local_startup(); le_CPU = (*(unsigned char *) &test_endian == 0 ? 0 : 1); /* Server isn't tested on big endian CPU */ ASSERT(le_CPU == 1); while(!unmountdone || !exitsignaled) { endpoint_t src; /* Wait for request message. */ get_work(&fs_m_in); transid = TRNS_GET_ID(fs_m_in.m_type); fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type); if (fs_m_in.m_type == 0) { assert(!IS_VFS_FS_TRANSID(transid)); fs_m_in.m_type = transid; /* Backwards compat. */ transid = 0; } else assert(IS_VFS_FS_TRANSID(transid)); src = fs_m_in.m_source; caller_uid = INVAL_UID; /* To trap errors */ caller_gid = INVAL_GID; req_nr = fs_m_in.m_type; if (req_nr < VFS_BASE) { fs_m_in.m_type += VFS_BASE; req_nr = fs_m_in.m_type; } ind = req_nr - VFS_BASE; if (ind < 0 || ind >= NREQS) { printf("mfs: bad request %d\n", req_nr); printf("ind = %d\n", ind); error = EINVAL; } else { error = (*fs_call_vec[ind])(); } fs_m_out.m_type = error; if (IS_VFS_FS_TRANSID(transid)) { /* If a transaction ID was set, reset it */ fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid); } reply(src, &fs_m_out); if (error == OK) read_ahead(); /* do block read ahead */ } return 0; }
/*===========================================================================* * main * *===========================================================================*/ int main(void) { /* This is the main program of the file system. The main loop consists of * three major activities: getting new work, processing the work, and sending * the reply. This loop never terminates as long as the file system runs. */ int transid; struct worker_thread *wp; /* SEF local startup. */ sef_local_startup(); printf("Started VFS: %d worker thread(s)\n", NR_WTHREADS); /* This is the main loop that gets work, processes it, and sends replies. */ while (TRUE) { worker_yield(); /* let other threads run */ send_work(); /* The get_work() function returns TRUE if we have a new message to * process. It returns FALSE if it spawned other thread activities. */ if (!get_work()) continue; transid = TRNS_GET_ID(m_in.m_type); if (IS_VFS_FS_TRANSID(transid)) { wp = worker_get((thread_t) transid - VFS_TRANSID); if (wp == NULL || wp->w_fp == NULL) { printf("VFS: spurious message %d from endpoint %d\n", m_in.m_type, m_in.m_source); continue; } m_in.m_type = TRNS_DEL_ID(m_in.m_type); do_reply(wp); continue; } else if (who_e == PM_PROC_NR) { /* Calls from PM */ /* Special control messages from PM */ service_pm(); continue; } else if (is_notify(call_nr)) { /* A task ipc_notify()ed us */ switch (who_e) { case DS_PROC_NR: /* Start a thread to handle DS events, if no thread * is pending or active for it already. DS is not * supposed to issue calls to VFS or be the subject of * postponed PM requests, so this should be no problem. */ if (worker_can_start(fp)) handle_work(ds_event); break; case KERNEL: mthread_stacktraces(); break; case CLOCK: /* Timer expired. Used only for select(). Check it. */ expire_timers(m_in.m_notify.timestamp); break; default: printf("VFS: ignoring notification from %d\n", who_e); } continue; } else if (who_p < 0) { /* i.e., message comes from a task */ /* We're going to ignore this message. Tasks should * send ipc_notify()s only. */ printf("VFS: ignoring message from %d (%d)\n", who_e, call_nr); continue; } if (IS_BDEV_RS(call_nr)) { /* We've got results for a block device request. */ bdev_reply(); } else if (IS_CDEV_RS(call_nr)) { /* We've got results for a character device request. */ cdev_reply(); } else { /* Normal syscall. This spawns a new thread. */ handle_work(do_work); } } return(OK); /* shouldn't come here */ }