diff --git a/executer/kernel/ikc.c b/executer/kernel/ikc.c index d571b52f..a2b7f010 100644 --- a/executer/kernel/ikc.c +++ b/executer/kernel/ikc.c @@ -43,7 +43,7 @@ static void mcctrl_ikc_init(ihk_os_t os, int cpu, unsigned long rphys, struct ih int mcexec_syscall(struct mcctrl_channel *c, int pid, unsigned long arg); void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg); void procfs_delete(void *__os, unsigned long arg); -void procfs_answer(unsigned long arg); +void procfs_answer(unsigned long arg, int err); static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, void *__packet, void *__os) @@ -77,7 +77,7 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, break; case SCD_MSG_PROCFS_ANSWER: - procfs_answer(pisp->arg); + procfs_answer(pisp->arg, pisp->err); break; } diff --git a/executer/kernel/procfs.c b/executer/kernel/procfs.c index b9eb5e80..2eacc10a 100644 --- a/executer/kernel/procfs.c +++ b/executer/kernel/procfs.c @@ -17,7 +17,7 @@ #include #include "mcctrl.h" -#define PROCFS_DEBUG +//#define PROCFS_DEBUG #ifdef PROCFS_DEBUG #define dprintk(...) printk(__VA_ARGS__) @@ -47,9 +47,11 @@ struct procfs_list_entry { LIST_HEAD(procfs_file_list); static ihk_spinlock_t procfs_file_list_lock; -/* - * char *p a name of the procfs file - * int mode if zero create a directory otherwise a file +/** + * \brief Return specified procfs entry. + * + * \param p a name of the procfs file + * \param mode if zero create a directory otherwise a file * * return value: NULL: Something wrong has occurred. * otherwise: address of the proc_dir_entry structure of the procfs file @@ -130,6 +132,16 @@ static struct proc_dir_entry *get_procfs_entry(char *p, int mode) return ret; } +/** + * \brief Create a procfs entry. + * + * \param __os (opeque) os variable + * \param ref cpuid of the requesting mckernel process + * \param osnum osnum of the requesting mckernel process + * \param pid pid of the requesting mckernel process + * \param arg sent argument + */ + void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg) { struct proc_dir_entry *entry; @@ -175,6 +187,13 @@ quit: dprintk("procfs_create: done\n"); } +/** + * \brief Delete a procfs entry. + * + * \param __os (opaque) os variable + * \param arg sent argument + */ + void procfs_delete(void *__os, unsigned long arg) { ihk_device_t dev = ihk_os_to_dev(__os); @@ -216,15 +235,22 @@ void procfs_delete(void *__os, unsigned long arg) dprintk("procfs_delete: done\n"); } -void procfs_answer(unsigned int arg) +/** + * \brief Process SCD_MSG_PROCFS_ANSWER message. + * + * \param arg sent argument + * \param err error info (redundant) + */ + +void procfs_answer(unsigned int arg, int err) { - dprintk("procfs: received SCD_MSG_PROCFS_ANSWER message.\n"); + dprintk("procfs: received SCD_MSG_PROCFS_ANSWER message(err = %d).\n", err); procfsq_channel = arg; wake_up_interruptible(&procfsq); } -/* - * callback funciton for McKernel procfs +/** + * \brief The callback funciton for McKernel procfs * * This function conforms to the 2) way of fs/proc/generic.c * from linux-2.6.39.4. @@ -238,11 +264,10 @@ int mckernel_procfs_read(char *buffer, char **start, off_t offset, struct procfs_list_entry *e = dat; struct procfs_read *r; struct ikc_scd_packet isp; - int ret; + int ret, retrycount = 0; unsigned long pbuf; dprintk("mckernel_procfs_read: invoked for %s\n", e->fname); - dprintk("offset: %lx, count: %d\n", offset, count); if (count <= 0 || dat == NULL) { return 0; @@ -258,9 +283,11 @@ int mckernel_procfs_read(char *buffer, char **start, off_t offset, return -ENOMEM; } retry: + dprintk("offset: %lx, count: %d, cpu: %d\n", offset, count, e->cpu); + r->pbuf = pbuf; r->eof = 0; - r->ret = 0; + r->ret = -EIO; /* default to error */ r->offset = offset; r->count = count; strncpy(r->fname, e->fname, PROCFS_NAME_MAX); @@ -281,6 +308,10 @@ retry: /* A miss-hit caused by migration has occurred. * We simply retry the query with a new CPU. */ + if (retrycount++ > 10) { + kprintf("ERROR: mckernel_procfs_read: excessive retry.\n"); + return -EIO; + } e->cpu = r->newcpu; dprintk("retry\n"); goto retry; @@ -288,10 +319,6 @@ retry: if (r->eof == 1) { *peof = 1; } - /* We employ the 2) method for a proc read function. - * Refer to fs/proc/generic.c of the Linux kernel - * for the details. - */ *start = buffer; ret = r->ret; kfree(r); @@ -299,16 +326,28 @@ retry: return ret; } -void procfs_init(int i) { +/** + * \brief Initialization for procfs + * + * \param osnum os number + */ + +void procfs_init(int osnum) { } -void procfs_exit(int i) { +/** + * \brief Finalization for procfs + * + * \param osnum os number + */ + +void procfs_exit(int osnum) { char buf[20]; int error; mm_segment_t old_fs = get_fs(); struct kstat stat; - sprintf(buf, "/proc/mcos%d", i); + sprintf(buf, "/proc/mcos%d", osnum); set_fs(KERNEL_DS); error = vfs_stat (buf, &stat); @@ -317,5 +356,6 @@ void procfs_exit(int i) { return; } + /* remove remnant of previous mcos%d */ remove_proc_entry(buf + 6, NULL); } diff --git a/kernel/init.c b/kernel/init.c index 21799eea..39deea57 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -35,7 +35,7 @@ #include #endif -#define DEBUG_PRINT_INIT +//#define DEBUG_PRINT_INIT #ifdef DEBUG_PRINT_INIT #define dkprintf kprintf diff --git a/kernel/procfs.c b/kernel/procfs.c index fbc1dbb0..ca3056fc 100644 --- a/kernel/procfs.c +++ b/kernel/procfs.c @@ -24,7 +24,7 @@ #include #include -#define DEBUG_PRINT_PROCFS +//#define DEBUG_PRINT_PROCFS #ifdef DEBUG_PRINT_PROCFS #define dprintf(...) kprintf(__VA_ARGS__) @@ -46,6 +46,13 @@ static void create_proc_procfs_file(int pid, char *fname, int mode, int cpuid); static void delete_proc_procfs_file(int pid, char *fname); static void operate_proc_procfs_file(int pid, char *fname, int msg, int mode, int cpuid); +/** + * \brief Create all procfs files for process. + * + * \param pid pid of the process + * \param cpuid cpuid of the process + */ + void create_proc_procfs_files(int pid, int cpuid) { char fname[PROCFS_NAME_MAX]; @@ -58,12 +65,27 @@ void create_proc_procfs_files(int pid, int cpuid) dprintf("create procfs files: done\n"); } +/** + * \brief Create a procfs file for process. + * + * \param pid pid of the process + * \param fname file name of the procfs file + * \param mode file mode + * \param cpuid cpuid of the process + */ + static void create_proc_procfs_file(int pid, char *fname, int mode, int cpuid) { dprintf("create procfs file: %s, mode: %o, cpuid: %d\n", fname, mode, cpuid); operate_proc_procfs_file(pid, fname, SCD_MSG_PROCFS_CREATE, mode, cpuid); } +/** + * \brief Delete all procfs files for process. + * + * \param pid pid of the process + */ + void delete_proc_procfs_files(int pid) { char fname[PROCFS_NAME_MAX]; @@ -89,6 +111,13 @@ void delete_proc_procfs_files(int pid) dprintf("delete procfs files: done\n"); } +/** + * \brief Delete a procfs file for process. + * + * \param pid pid of the process + * \param fname file name of the procfs file + */ + static void delete_proc_procfs_file(int pid, char *fname) { dprintf("delete procfs file: %s\n", fname); @@ -96,6 +125,16 @@ static void delete_proc_procfs_file(int pid, char *fname) dprintf("delete procfs file: %s done\n", fname); } +/** + * \brief Create/delete a procfs file for process. + * + * \param pid pid of the process + * \param fname file name of the procfs file + * \param msg message (create/delete) + * \param mode file mode + * \param cpuid cpuid of the process + */ + static void operate_proc_procfs_file(int pid, char *fname, int msg, int mode, int cpuid) { struct ihk_ikc_channel_desc *syscall_channel; @@ -132,89 +171,165 @@ static void operate_proc_procfs_file(int pid, char *fname, int msg, int mode, in kfree(f); } +/** + * \brief The callback function for mckernel procfs files. + * + * \param rarg returned argument + */ + void process_procfs_request(unsigned long rarg) { unsigned long parg, pbuf; struct process *proc = cpu_local_var(current); struct procfs_read *r; struct ikc_scd_packet packet; - int rosnum, ret, pid, tid, ans = -ENOENT, eof = 0; - char *buf; + int rosnum, ret, pid, tid, ans = -EIO, eof = 0; + char *buf, *p; struct ihk_ikc_channel_desc *syscall_channel; dprintf("process_procfs_request: invoked.\n"); syscall_channel = get_cpu_local_var(0)->syscall_channel; + dprintf("rarg: %x\n", rarg); parg = ihk_mc_map_memory(NULL, rarg, sizeof(struct procfs_read)); + dprintf("parg: %x\n", parg); r = ihk_mc_map_virtual(parg, sizeof(struct procfs_read), PTATTR_WRITABLE | PTATTR_ACTIVE); + dprintf("r: %p\n", r); + if (r == NULL) { + kprintf("ERROR: process_procfs_request: got a null procfs_read structure.\n"); + packet.err = -EIO; + goto dataunavail; + } + dprintf("remote pbuf: %x\n", r->pbuf); pbuf = ihk_mc_map_memory(NULL, r->pbuf, r->count); + dprintf("pbuf: %x\n", pbuf); buf = ihk_mc_map_virtual(pbuf, r->count, PTATTR_WRITABLE | PTATTR_ACTIVE); + dprintf("buf: %p\n", buf); + if (buf == NULL) { + kprintf("ERROR: process_procfs_request: got a null buffer.\n"); + packet.err = -EIO; + goto bufunavail; + } dprintf("fname: %s, offset: %lx, count:%d.\n", r->fname, r->offset, r->count); - /* mcos0/PID/taks/PID/mem - * - * The offset is treated as the beginning of the virtual address area - * of the process. The count is the length of the area. + /* + * check for "mcos%d/" */ - ret = sscanf(r->fname, "mcos%d/%d/task/%d/mem", &rosnum, &pid, &tid); - if ((ret == 3) && (pid == tid) && (osnum == rosnum)) { - if (cpu_local_var(current)->pid != pid) { - /* The target process has gone by migration. */ -#ifdef FIXME - r->newcpu = ... -#endif - ans = 0; - } else { - struct vm_range *range; - struct process_vm *vm = proc->vm; - ans = -EIO; /* default to an I/O error */ - list_for_each_entry(range, &vm->vm_range_list, list) { - dprintf("range: %lx - %lx\n", range->start, range->end); - if ((range->start <= r->offset) && - (r->offset < range->end)) { - unsigned int len = r->count; - if (range->end < r->offset + r->count) { - len = range->end - r->offset; - } - memcpy((void *) buf, (void *)range->start, len); - ans = len; - break; - } - } + ret = sscanf(r->fname, "mcos%d/", &rosnum); + if (ret == 1) { + if (osnum != rosnum) { + kprintf("ERROR: process_procfs_request osnum mismatch " + "(we are %d != requested %d)\n", + osnum, rosnum); + goto end; } + dprintf("matched mcos%d.\n", osnum); + } else { goto end; } + p = strchr(r->fname, '/') + 1; - /* Processing of other kinds of procfs files should be located here. + /* Processing for pattern "mcos%d/xxx" files should be here. Its template is something like what follows: - ret = scanf(r->fname, "mcos%d/PATTERN", ...) - if ((ret == x) && pattern has matched) { - get the data and write it to the buffer; + ret = sscanf(p, "PATTERN", ...) + if ((ret == xx) && pattern has matched) { + get the data (at 'r->offset') + and write it to 'buf' + up to 'r->count' bytes. ans = written bytes; goto end; } */ + /* + * check for "mcos%d/PID/" + */ + ret = sscanf(p, "%d/", &pid); + if (ret == 1) { + if (pid != cpu_local_var(current)->pid) { + /* We are not located in the proper cpu for some reason. */ + void *savelock; + unsigned long irqstate; + struct process *proc; + + dprintf("mismatched pid. We are %d, but requested pid is %d.\n", + pid, cpu_local_var(current)->pid); + if ((proc = findthread_and_lock(pid, tid, &savelock, &irqstate))){ + /* The target process has gone by migration. */ + r->newcpu = proc->cpu_id; + dprintf("expected cpu id is %d.\n", proc->cpu_id); + process_unlock(savelock, irqstate); + ans = 0; + } else { + dprintf("We cannot find the proper cpu for requested pid.\n"); + } + goto end; + } + } else { + goto end; + } + dprintf("matched PID: %d.\n", pid); + p = strchr(p, '/') + 1; + + /* + * mcos0/PID/taks/PID/mem + * + * The offset is treated as the beginning of the virtual address area + * of the process. The count is the length of the area. + */ + ret = sscanf(p, "task/%d/mem", &tid); + if (ret == 1) { + struct vm_range *range; + struct process_vm *vm = proc->vm; + + if (pid != tid) { + /* We are not multithreaded yet. */ + goto end; + } + list_for_each_entry(range, &vm->vm_range_list, list) { + dprintf("range: %lx - %lx\n", range->start, range->end); + if ((range->start <= r->offset) && + (r->offset < range->end)) { + unsigned int len = r->count; + if (range->end < r->offset + r->count) { + len = range->end - r->offset; + } + memcpy((void *) buf, (void *)range->start, len); + ans = len; + break; + } + } + goto end; + } + + /* + * Processing for pattern "mcos%d/PID/xxx" files should be here. + */ + dprintf("could not find a matching entry for %s.\n", p); end: - dprintf("read: %d, eof: %d\n", ans, eof); + ihk_mc_unmap_virtual(buf, r->count, 0); + dprintf("ret: %d, eof: %d\n", ans, eof); r->ret = ans; r->eof = eof; + packet.err = 0; +bufunavail: + ihk_mc_unmap_memory(NULL, pbuf, r->count); + ihk_mc_unmap_virtual(r, sizeof(struct procfs_read), 0); +dataunavail: + ihk_mc_unmap_memory(NULL, parg, sizeof(struct procfs_read)); + packet.msg = SCD_MSG_PROCFS_ANSWER; packet.arg = rarg; - - ihk_mc_unmap_virtual(buf, r->count, 0); - ihk_mc_unmap_memory(NULL, pbuf, r->count); - - ihk_mc_unmap_virtual(r, sizeof(struct procfs_read), 0); - ihk_mc_unmap_memory(NULL, parg, sizeof(struct procfs_read)); ret = ihk_ikc_send(syscall_channel, &packet, 0); if (ret < 0) { kprintf("ERROR: sending IKC msg, ret: %d\n", ret); } + return; + } diff --git a/lib/include/string.h b/lib/include/string.h index e34afe58..0c10d1af 100644 --- a/lib/include/string.h +++ b/lib/include/string.h @@ -22,6 +22,7 @@ char *strncpy(char *dest, const char *src, size_t maxlen); int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); char *strstr(const char *haystack, const char *needle); +char *strchr(const char *s, int n); void *memcpy(void *dest, const void *src, size_t n); void *memcpy_long(void *dest, const void *src, size_t n); int memcmp(const void *s1, const void *s2, size_t n); diff --git a/lib/string.c b/lib/string.c index 41f58a40..4509630c 100644 --- a/lib/string.c +++ b/lib/string.c @@ -80,6 +80,21 @@ int strncmp(const char *s1, const char *s2, size_t n) return *s1 - *s2; } +char *strchr(const char *s, int n) { + char *p = (char *)s; + while (1) { + if (*p == n) + { + return p; + } else if (*p == '\0') { + break; + } + ++p; + } + return NULL; +} + + char *strstr(const char *haystack, const char *needle) { int len = strlen(needle);