📄 dispatcher.c
字号:
struct uip_conn *c; c = uip_connect(ripaddr, port); if(c == NULL) { return NULL; } dispatcher_emit(uip_signal_poll, c, DISPATCHER_BROADCAST); dispatcher_markconn(c, appstate); return c;}/*-----------------------------------------------------------------------------------*//** * \internal The uIP callback function. * * This function is the uIP callback function and is called by the uIP * code whenever a uIP event occurs. This funcion will find out to * which process the event should be handed over to, and calls the * appropriate process' uIP callback function if such a function has * been registered. * *//*-----------------------------------------------------------------------------------*/#ifdef WITH_UIPvoiddispatcher_uipcall(void) { register struct dispatcher_proc *p; register struct dispatcher_uipstate *s; static u8_t i; struct listenport *l; s = (struct dispatcher_uipstate *)uip_conn->appstate; /* If this is a connection request for a listening port, we must mark the connection with the right process ID. */ if(uip_connected()) { l = &listenports[0]; for(i = 0; i < UIP_LISTENPORTS; ++i) { if(l->port == uip_conn->lport && l->id != EK_ID_NONE) { s->id = l->id; s->state = NULL; break; } ++l; } } for(p = dispatcher_procs; p != NULL; p = p->next) { if(p->id == s->id && p->uiphandler != NULL) { dispatcher_current = p->id; curproc = p;#if CC_FUNCTION_POINTER_ARGS p->uiphandler(s->state);#else /* CC_FUNCTION_POINTER_ARGS */ dispatcher_uipcall_state = s->state; p->uiphandler();#endif /* CC_FUNCTION_POINTER_ARGS */ return; } } /* If we get here, the process that created the connection has exited, so we abort this connection. */ uip_abort();}#endif /* WITH_UIP *//*-----------------------------------------------------------------------------------*//** * Opens a TCP port for incoming requests. * * * * \param port The TCP port number that should be opened for * listening, in network byte order. *//*-----------------------------------------------------------------------------------*/voiddispatcher_uiplisten(u16_t port){ static unsigned char i; struct listenport *l; l = listenports; for(i = 0; i < UIP_LISTENPORTS; ++i) { if(l->port == 0) { l->port = port; l->id = dispatcher_current;#ifdef WITH_UIP uip_listen(port);#endif /* WITH_UIP */ break; } ++l; }}/*-----------------------------------------------------------------------------------*//** * Associates a generic pointer with a uIP connection. * * This function is used for registering a pointer to a uIP * connection. This pointer will be passed as an argument to the * process' uIP handler function for every uIP event. * * \param conn The uIP connection to which the pointer is to be * associated. * * \param appstate The generic pointer that is to be associated with * the uIP connection. *//*-----------------------------------------------------------------------------------*/voiddispatcher_markconn(struct uip_conn *conn, void *appstate){ struct dispatcher_uipstate *s; s = (struct dispatcher_uipstate *)conn->appstate; s->id = dispatcher_current; s->state = appstate;}/*-----------------------------------------------------------------------------------*//** * Registers the calling process as a listener for a signal. * * \param s The signal to which the process should listen. * *//*-----------------------------------------------------------------------------------*/voiddispatcher_listen(ek_signal_t s){ if(curproc != NULL) { curproc->signals[s] = 1; }}/*-----------------------------------------------------------------------------------*//** * Finds the process structure for a specific process ID. * * \param id The process ID for the process. * * \return The process structure for the process, or NULL if there * process ID was not found. *//*-----------------------------------------------------------------------------------*/struct dispatcher_proc *dispatcher_process(ek_id_t id){ struct dispatcher_proc *p; for(p = dispatcher_procs; p != NULL; p = p->next) { if(p->id == id) { return p; } } return NULL;}/*-----------------------------------------------------------------------------------*//** * Initializes the dispatcher module. * * Must be called during the initialization of Contiki. * *//*-----------------------------------------------------------------------------------*/voiddispatcher_init(void){ static unsigned char i; for(i = 0; i < UIP_LISTENPORTS; ++i) { listenports[i].port = 0; } lastsig = 1; dispatcher_signal_quit = dispatcher_sigalloc(); nsignals = fsignal = 0; arg_init();}/*-----------------------------------------------------------------------------------*//** * \internal Delivers a signal to specific process. * * \param s The signal number * \param data The signal data pointer * \param id The process to which the signal should be delivered *//*-----------------------------------------------------------------------------------*/static void CC_FASTCALLdeliver(ek_signal_t s, ek_data_t data, ek_id_t id){ struct dispatcher_proc *p; for(p = dispatcher_procs; p != NULL; p = p->next) { if((id == DISPATCHER_BROADCAST || p->id == id) && p->signals[s] != 0 && p->signalhandler != NULL) { dispatcher_current = p->id; curproc = p;#if CC_FUNCTION_POINTER_ARGS p->signalhandler(s, data);#else /* CC_FUNCTION_POINTER_ARGS */ dispatcher_sighandler_s = s; dispatcher_sighandler_data = data; p->signalhandler();#endif /* CC_FUNCTION_POINTER_ARGS */ } } }/*-----------------------------------------------------------------------------------*//** * Emits a signal, and delivers the signal immediately. * * This function emits a signal and calls the listening processes' * signal handlers immediately, before returning to the caller. This * function requires more call stack space than the dispatcher_emit() * function and should be used with care, and only in situtations * where the exact implications are known. * * In most situations, the dispatcher_emit() function should be used * instead. * * \param s The signal to be emitted. * * \param data The auxillary data to be sent with the signal * * \param id The process ID to which the signal should be emitted, or * DISPATCHER_BROADCAST if the signal should be emitted to all * processes listening for the signal. * *//*-----------------------------------------------------------------------------------*/voiddispatcher_fastemit(ek_signal_t s, ek_data_t data, ek_id_t id){ ek_id_t pid; struct dispatcher_proc *p; pid = dispatcher_current; p = curproc; deliver(s, data, id); dispatcher_current = pid; curproc = p; }/*-----------------------------------------------------------------------------------*//** * Process the next signal in the signal queue and deliver it to * listening processes. * *//*-----------------------------------------------------------------------------------*/voiddispatcher_process_signal(void){ static ek_signal_t s; static ek_data_t data; static ek_id_t id; /* If there are any signals in the queue, take the first one and walk through the list of processes to see if the signal should be delivered to any of them. If so, we call the signal handler function for the process. We only process one signal at a time and call the idle handlers inbetween. */ if(nsignals > 0) { /* There are signals that we should deliver. */ s = signals[fsignal].s; data = signals[fsignal].data; id = signals[fsignal].id; /* Since we have seen the new signal, we move pointer upwards and decrese number. */ fsignal = (fsignal + 1) % EK_CONF_NUMSIGNALS; --nsignals; deliver(s, data, id); }}/*-----------------------------------------------------------------------------------*//** * Call each process' idle handler. *//*-----------------------------------------------------------------------------------*/voiddispatcher_process_idle(void){ struct dispatcher_proc *p; /* Call idle handlers. */ for(p = dispatcher_procs; p != NULL; p = p->next) { if(p->idle != NULL) { dispatcher_current = p->id; curproc = p; p->idle(); } } }/*-----------------------------------------------------------------------------------*//** * Run the system - process signals and call idle handlers. * * This function should be called after all other initialization * stuff, and will never return. *//*-----------------------------------------------------------------------------------*/voiddispatcher_run(void){ while(1) { /* Process one signal */ dispatcher_process_signal(); /* Run "idle" handlers */ dispatcher_process_idle(); }}/*-----------------------------------------------------------------------------------*//** * Emits a signal to a process. * * \param s The signal to be emitted. * * \param data The auxillary data to be sent with the signal * * \param id The process ID to which the signal should be emitted, or * DISPATCHER_BROADCAST if the signal should be emitted to all * processes listening for the signal. * * \retval EK_ERR_OK The signal could be emitted. * * \retval EK_ERR_FULL The signal queue was full and the signal could * not be emitted *//*-----------------------------------------------------------------------------------*/ek_err_tdispatcher_emit(ek_signal_t s, ek_data_t data, ek_id_t id){ static unsigned char snum; if(nsignals == EK_CONF_NUMSIGNALS) { return EK_ERR_FULL; } if(s != EK_SIGNAL_NONE) { snum = (fsignal + nsignals) % EK_CONF_NUMSIGNALS; signals[snum].s = s; signals[snum].data = data; signals[snum].id = id; ++nsignals; } return EK_ERR_OK;}/*-----------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -