/*===========================================================================* * sys_task * *===========================================================================*/ PUBLIC void sys_task() { /* Main entry point of sys_task. Get the message and dispatch on type. */ /* 系统调用的主要入口点. 获取消息, 再根据类型分派. */ static message m; register int result; register struct proc *caller_ptr; unsigned int call_nr; int s; /* Initialize the system task. */ /* 初始化系统任务. */ // 初始化系统调用 initialize(); while (TRUE) { /* Get work. Block and wait until a request message arrives. */ /* 开始工作. 阻塞, 直到一个请求消息到来. */ receive(ANY, &m); // 系统调用向量号 call_nr = (unsigned) m.m_type - KERNEL_CALL; // 请求系统调用的进程指针 caller_ptr = proc_addr(m.m_source); /* See if the caller made a valid request and try to handle it. */ // 检查主调进程是否有能力请求该系统调用. if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr))) { kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source); result = ECALLDENIED; /* illegal message type */ } else if (call_nr >= NR_SYS_CALLS) { /* check call number */ // 检查系统调用向量号的合法性. kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source); result = EBADREQUEST; /* illegal message type */ } else { // 执行系统调用. result = (*call_vec[call_nr])(&m); /* handle the kernel call */ } /* Send a reply, unless inhibited by a handler function. Use the kernel * function lock_send() to prevent a system call trap. The destination * is known to be blocked waiting for a message. */ /* * 发送一个回复, 除非被系统调用处理函数禁止了. 使得系统函数 * lock_send() 来禁止系统调用陷入. 已知目标进程因为等待一个消息而 * 阻塞. */ if (result != EDONTREPLY) { // 将系统调用的执行结果发送给系统调用的主调进程. m.m_type = result; /* report status of call */ if (OK != (s=lock_send(m.m_source, &m))) { kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s); } } } }
/*===========================================================================* * sys_task * *===========================================================================*/ PUBLIC void sys_task() { /* Main entry point of sys_task. Get the message and dispatch on type. */ static message m; register int result; register struct proc *caller_ptr; unsigned int call_nr; int s; /* Initialize the system task. */ initialize(); while (TRUE) { /* Get work. Block and wait until a request message arrives. */ receive(ANY, &m); call_nr = (unsigned) m.m_type - KERNEL_CALL; who_e = m.m_source; okendpt(who_e, &who_p); caller_ptr = proc_addr(who_p); /* See if the caller made a valid request and try to handle it. */ if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr))) { #if DEBUG_ENABLE_IPC_WARNINGS kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source); #endif result = ECALLDENIED; /* illegal message type */ } else if (call_nr >= NR_SYS_CALLS) { /* check call number */ #if DEBUG_ENABLE_IPC_WARNINGS kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source); #endif result = EBADREQUEST; /* illegal message type */ } else { result = (*call_vec[call_nr])(&m); /* handle the system call */ } /* Send a reply, unless inhibited by a handler function. Use the kernel * function lock_send() to prevent a system call trap. The destination * is known to be blocked waiting for a message. */ if (result != EDONTREPLY) { m.m_type = result; /* report status of call */ if (OK != (s=lock_send(m.m_source, &m))) { kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s); } } } }
static void reopen_file(struct tevent_context *ev, struct tevent_timer *te, struct timeval t, void *private_data) { struct benchlock_state *state = (struct benchlock_state *)private_data; /* reestablish our open file */ state->fnum = smbcli_open(state->tree, FNAME, O_RDWR|O_CREAT, DENY_NONE); if (state->fnum == -1) { printf("Failed to open %s on connection %d\n", FNAME, state->client_num); exit(1); } num_connected++; DEBUG(0,("reconnect to %s finished (%u connected)\n", state->dest_host, num_connected)); state->stage = LOCK_INITIAL; lock_send(state); }
/* called when a lock completes */ static void lock_completion(struct smbcli_request *req) { struct benchlock_state *state = (struct benchlock_state *)req->async.private_data; NTSTATUS status = smbcli_request_simple_recv(req); state->req = NULL; if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) || NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT) || NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) { talloc_free(state->tree); state->tree = NULL; num_connected--; DEBUG(0,("reopening connection to %s\n", state->dest_host)); talloc_free(state->te); state->te = event_add_timed(state->ev, state->mem_ctx, timeval_current_ofs(1,0), reopen_connection, state); } else { DEBUG(0,("Lock failed - %s\n", nt_errstr(status))); lock_failed++; } return; } switch (state->stage) { case LOCK_INITIAL: state->stage = LOCK_LOCK; break; case LOCK_LOCK: state->stage = LOCK_UNLOCK; break; case LOCK_UNLOCK: state->stage = LOCK_LOCK; break; } state->count++; lock_send(state); }
/*===========================================================================* * sys_task * *===========================================================================*/ PUBLIC void sys_task() { /* Main entry point of sys_task. Get the message and dispatch on type. */ static message m; register int result; register struct proc *caller_ptr; int s; int call_nr; int n = 0; /* Initialize the system task. */ initialize(); while (TRUE) { struct proc *restarting; restarting = vmrestart_check(&m); if(!restarting) { int r; /* Get work. Block and wait until a request message arrives. */ if((r=receive(ANY, &m)) != OK) minix_panic("receive() failed", r); } sys_call_code = (unsigned) m.m_type; call_nr = sys_call_code - KERNEL_CALL; who_e = m.m_source; okendpt(who_e, &who_p); caller_ptr = proc_addr(who_p); /* See if the caller made a valid request and try to handle it. */ if (call_nr < 0 || call_nr >= NR_SYS_CALLS) { /* check call number */ kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source); result = EBADREQUEST; /* illegal message type */ } else if (!GET_BIT(priv(caller_ptr)->s_k_call_mask, call_nr)) { result = ECALLDENIED; /* illegal message type */ } else { result = (*call_vec[call_nr])(&m); /* handle the system call */ } if(result == VMSUSPEND) { /* Special case: message has to be saved for handling * until VM tells us it's allowed. VM has been notified * and we must wait for its reply to restart the call. */ vmassert(RTS_ISSET(caller_ptr, VMREQUEST)); vmassert(caller_ptr->p_vmrequest.type == VMSTYPE_KERNELCALL); memcpy(&caller_ptr->p_vmrequest.saved.reqmsg, &m, sizeof(m)); } else if (result != EDONTREPLY) { /* Send a reply, unless inhibited by a handler function. * Use the kernel function lock_send() to prevent a system * call trap. */ if(restarting) { vmassert(!RTS_ISSET(restarting, VMREQUEST)); #if 0 vmassert(!RTS_ISSET(restarting, VMREQTARGET)); #endif } m.m_type = result; /* report status of call */ if(WILLRECEIVE(caller_ptr, SYSTEM)) { if (OK != (s=lock_send(m.m_source, &m))) { kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s); } } else { kprintf("SYSTEM: not replying to %d; not ready\n", caller_ptr->p_endpoint); } } } }
/* benchmark locking calls */ bool torture_bench_lock(struct torture_context *torture) { bool ret = true; TALLOC_CTX *mem_ctx = talloc_new(torture); int i, j; int timelimit = torture_setting_int(torture, "timelimit", 10); struct timeval tv; struct benchlock_state *state; int total = 0, minops=0; struct smbcli_state *cli; bool progress; off_t offset; int initial_locks = torture_setting_int(torture, "initial_locks", 0); progress = torture_setting_bool(torture, "progress", true); nprocs = torture_setting_int(torture, "nprocs", 4); state = talloc_zero_array(mem_ctx, struct benchlock_state, nprocs); printf("Opening %d connections\n", nprocs); for (i=0;i<nprocs;i++) { state[i].tctx = torture; state[i].mem_ctx = talloc_new(state); state[i].client_num = i; state[i].ev = torture->ev; if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) { return false; } talloc_steal(mem_ctx, state); state[i].tree = cli->tree; state[i].dest_host = talloc_strdup(state[i].mem_ctx, cli->tree->session->transport->socket->hostname); state[i].dest_ports = talloc_array(state[i].mem_ctx, const char *, 2); state[i].dest_ports[0] = talloc_asprintf(state[i].dest_ports, "%u", cli->tree->session->transport->socket->port); state[i].dest_ports[1] = NULL; state[i].called_name = talloc_strdup(state[i].mem_ctx, cli->tree->session->transport->called.name); state[i].service_type = talloc_strdup(state[i].mem_ctx, cli->tree->device); } num_connected = i; if (!torture_setup_dir(cli, BASEDIR)) { goto failed; } for (i=0;i<nprocs;i++) { state[i].fnum = smbcli_open(state[i].tree, FNAME, O_RDWR|O_CREAT, DENY_NONE); if (state[i].fnum == -1) { printf("Failed to open %s on connection %d\n", FNAME, i); goto failed; } /* Optionally, lock initial_locks for each proc beforehand. */ if (i == 0 && initial_locks > 0) { printf("Initializing %d locks on each proc.\n", initial_locks); } for (j = 0; j < initial_locks; j++) { offset = (0xFFFFFED8LLU * (i+2)) + j; if (!NT_STATUS_IS_OK(smbcli_lock64(state[i].tree, state[i].fnum, offset, 1, 0, WRITE_LOCK))) { printf("Failed initializing, lock=%d\n", j); goto failed; } } state[i].stage = LOCK_INITIAL; lock_send(&state[i]); } tv = timeval_current(); if (progress) { event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state); } printf("Running for %d seconds\n", timelimit); while (timeval_elapsed(&tv) < timelimit) { event_loop_once(torture->ev); if (lock_failed) { DEBUG(0,("locking failed\n")); goto failed; } } printf("%.2f ops/second\n", total/timeval_elapsed(&tv)); minops = state[0].count; for (i=0;i<nprocs;i++) { printf("[%d] %u ops\n", i, state[i].count); if (state[i].count < minops) minops = state[i].count; } if (minops < 0.5*total/nprocs) { printf("Failed: unbalanced locking\n"); goto failed; } for (i=0;i<nprocs;i++) { talloc_free(state[i].req); smb_raw_exit(state[i].tree->session); } smbcli_deltree(state[0].tree, BASEDIR); talloc_free(mem_ctx); printf("\n"); return ret; failed: smbcli_deltree(state[0].tree, BASEDIR); talloc_free(mem_ctx); return false; }