📄 ndis_dispatch.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)ndis_dispatch.c 1.1 92/07/30 Copyr 1985 Sun Micro";#endif#endif /* * Copyright (c) 1985 by Sun Microsystems, Inc. *//* * Ndis_dispatch.c - Central control mechanism for the dispatcher. */#include <sunwindow/ntfy.h>#include <sunwindow/ndis.h>#include <sunwindow/nint.h>#include <sunwindow/ndet.h> /* For ndet_set_event_processing/ndet_flags */#include <signal.h>/* performance: global cache of getdtablesize() */extern int dtablesize_cache;#define GETDTABLESIZE() \ (dtablesize_cache?dtablesize_cache:(dtablesize_cache=getdtablesize()))pkg_private_data u_int ndis_flags = 0;pkg_private_data NTFY_CLIENT *ndis_clients = 0;pkg_private_data NTFY_CLIENT *ndis_client_latest = 0;pkg_private_data Notify_value (*ndis_scheduler)() = ndis_default_scheduler;static Notify_client *ndis_sched_nclients;/* Parallel data structure to ndis_clients for use with scheduler*/static u_int ndis_sched_count; /* Last valid position (plus one) in ndis_sched_nclients */static u_int ndis_sched_length; /* Current length of ndis_sched_nclients */static Notify_event *ndis_events; /* List of events currently being dispatched for a given client */static Notify_arg *ndis_args; /* List of event args currently being dispatched for a given client (parallels ndis_events) */static u_int ndis_event_count; /* Last valid position (plus one) in ndis_events & ndis_args */static u_int ndis_event_length; /* Current length of ndis_events & ndis_args */static Notify_error ndis_send_func(); /* Used to get func for sending notify*/#define NDIS_RELEASE_NULL ((Notify_release *)0)static NTFY_ENUM ndis_setup_sched_clients();/* Enqueue condition from dectector on to the dispatchers client list */pkg_private Notify_errorndis_enqueue(ndet_client, ndet_condition) register NTFY_CLIENT *ndet_client; register NTFY_CONDITION *ndet_condition;{ register NTFY_CLIENT *client; register NTFY_CONDITION *condition; ntfy_assert(NTFY_IN_CRITICAL, "Not protected when enqueue condition"); /* Find/create client that corresponds to ndet_client */ if ((client = ntfy_new_nclient(&ndis_clients, ndet_client->nclient, &ndis_client_latest)) == NTFY_CLIENT_NULL) goto Error; client->prioritizer = ndet_client->prioritizer; /* Allocate condition */ if ((condition = ntfy_alloc_condition()) == NTFY_CONDITION_NULL) goto Error; /* Initialize condition */ condition->next = NTFY_CONDITION_NULL; condition->type = ndet_condition->type; condition->release = ndet_condition->release; condition->arg = ndet_condition->arg; switch (condition->type) { case NTFY_REAL_ITIMER: case NTFY_VIRTUAL_ITIMER: condition->data.an_u_int = 0; break; case NTFY_WAIT3: if ((condition->data.wait3 = (NTFY_WAIT3_DATA *) ntfy_malloc( sizeof(NTFY_WAIT3_DATA))) == NTFY_WAIT3_DATA_NULL) goto Error; *condition->data.wait3 = *ndet_condition->data.wait3; break; default: condition->data.an_u_int = ndet_condition->data.an_u_int; break; } condition->func_count = ndet_condition->func_count; condition->func_next = 0; if (nint_copy_callout(condition, ndet_condition) != NOTIFY_OK) goto Error; /* Append to condition list */ ntfy_append_condition(&(client->conditions), condition); /* Set up condition hint */ client->condition_latest = condition; /* Set dispatcher flag */ ndis_flags |= NDIS_EVENT_QUEUED; return(NOTIFY_OK);Error: return(notify_errno);}/* Dispatch to all clients according to the scheduler */pkg_private Notify_errorndis_dispatch(){ Notify_value (*sched_func)(); /* Quick bailout if nothing to send */ if (ndis_clients == NTFY_CLIENT_NULL) return(NOTIFY_OK); ntfy_assert(!NTFY_IN_CRITICAL, "In critical when dispatch"); ntfy_assert(!NTFY_IN_INTERRUPT, "In interrupt when dispatch"); NTFY_BEGIN_CRITICAL; /* Build nclient list for scheduler */ for (;;) { ndis_sched_count = 0; /* If enumerator returns NTFY_ENUM_TERM then list too short */ if (ntfy_enum_conditions(ndis_clients, ndis_setup_sched_clients, NTFY_ENUM_DATA_NULL) == NTFY_ENUM_TERM) { /* Free previous list */ if (ndis_sched_nclients) ntfy_free_malloc( (NTFY_DATA)ndis_sched_nclients); /* Allocate new list */ ndis_sched_length += 20; if ((ndis_sched_nclients = (Notify_client *) ntfy_malloc(ndis_sched_length*sizeof(Notify_client))) == (Notify_client *)0) { NTFY_END_CRITICAL; return(notify_errno); } } else break; } /* Call scheduler */ sched_func = ndis_scheduler; NTFY_END_CRITICAL; if (sched_func(ndis_sched_count, ndis_sched_nclients) == NOTIFY_UNEXPECTED) /* * Scheduler sets notify_errno and returns error if there * is some non-callout related problem. */ return(notify_errno); return(NOTIFY_OK);}/* ARGSUSED */static NTFY_ENUMndis_setup_sched_clients(client, condition, context) NTFY_CLIENT *client; NTFY_CONDITION *condition; NTFY_ENUM_DATA context;{ /* Terminate enumeration if next slot overflows size of client table */ if (ndis_sched_count == ndis_sched_length) return(NTFY_ENUM_TERM); *(ndis_sched_nclients+ndis_sched_count) = client->nclient; ndis_sched_count++; return(NTFY_ENUM_SKIP);}/* Flush given nclient & its conditions */extern voidnotify_flush_pending(nclient) Notify_client nclient;{ NTFY_CLIENT *client; register int i; NTFY_BEGIN_CRITICAL; if ((client = ntfy_find_nclient(ndis_clients, nclient, &ndis_client_latest)) == NTFY_CLIENT_NULL) goto Done; else { /* Flush any pending notification from dispatcher */ ntfy_remove_client(&ndis_clients, client, &ndis_client_latest, NTFY_NDIS); /* Remove nclient from list of clients to be scheduled */ for (i = 0; i < ndis_sched_length; i++) if (ndis_sched_nclients[i] == nclient) ndis_sched_nclients[i] = NOTIFY_CLIENT_NULL; /* * The dispatcher may be calling out to an nclient at this time. * When an nclient calls back in, we always check the validity * of the handle. Thus, the dispatcher ignores any further * references to client. */ }Done: NTFY_END_CRITICAL; return;}extern Notify_errornotify_client(nclient) Notify_client nclient;{ NTFY_CLIENT *client; register NTFY_CONDITION *cdn; int sigbits, auto_sigbits; fd_set ibits, obits, ebits; /* Don't make register because take address of them */ Notify_value (*pri_func)(); int maxfds = GETDTABLESIZE(); /* Check if heap access protected */ ntfy_assert(!NTFY_IN_INTERRUPT, "In interrupt when notify"); NTFY_BEGIN_CRITICAL;Retry_Client: /* Find client */ if ((client = ntfy_find_nclient(ndis_clients, nclient, &ndis_client_latest)) == NTFY_CLIENT_NULL) /* Can get here on first time if client removed pending cond */ goto Done; /* Reset flags that detects when another condition enqueued */ ndis_flags &= ~NDIS_EVENT_QUEUED;Retry_Conditions: /* Initialize prioritizer arguments */ sigbits = auto_sigbits = 0; FD_ZERO(&ibits); FD_ZERO(&obits); FD_ZERO(&ebits); ndis_event_count = 0; /* Fill out prioritizer arguments based on conditions */ for (cdn = client->conditions; cdn; cdn = cdn->next) { switch (cdn->type) { case NTFY_INPUT: FD_SET(cdn->data.fd, &ibits); break; case NTFY_OUTPUT: FD_SET(cdn->data.fd, &obits); break; case NTFY_EXCEPTION: FD_SET(cdn->data.fd, &ebits); break; case NTFY_SYNC_SIGNAL: sigbits |= SIG_BIT(cdn->data.signal); break; case NTFY_REAL_ITIMER: auto_sigbits |= SIG_BIT(SIGALRM); break; case NTFY_VIRTUAL_ITIMER: auto_sigbits |= SIG_BIT(SIGVTALRM); break; case NTFY_WAIT3: auto_sigbits |= SIG_BIT(SIGCHLD); break; case NTFY_DESTROY: switch (cdn->data.status) { case DESTROY_CLEANUP: auto_sigbits |= SIG_BIT(SIGTERM); break; case DESTROY_PROCESS_DEATH: auto_sigbits |= SIG_BIT(SIGKILL); break; case DESTROY_CHECKING: auto_sigbits |= SIG_BIT(SIGTSTP); break; } break; case NTFY_SAFE_EVENT: /* * Build event list for prioritizer. * Terminate condition traversal if next slot * overflows size of event table. */ if (ndis_event_count == ndis_event_length) { /* Free previous list */ if (ndis_events) { ntfy_free_malloc( (NTFY_DATA)ndis_events); ntfy_free_malloc( (NTFY_DATA)ndis_args); } /* Allocate new list */ ndis_event_length += 20; if ((ndis_events = (Notify_event *) ntfy_malloc(ndis_event_length* sizeof(Notify_event))) == (Notify_event *)0) goto Error; if ((ndis_args = (Notify_arg *) ntfy_malloc(ndis_event_length* sizeof(Notify_arg))) == (Notify_arg *)0) goto Error; /* Restart condition traversal */ goto Retry_Conditions; } *(ndis_events+ndis_event_count) = cdn->data.event; *(ndis_args+ndis_event_count) = cdn->arg; ndis_event_count++; break; default: ntfy_fatal_error("Unexpected dispatcher cond"); } } /* Call prioritizer */ pri_func = client->prioritizer; NTFY_END_CRITICAL;/* the second arg to pri_func should be max fd # for select call ??? */ (void) pri_func(nclient, maxfds, &ibits, &obits, &ebits, NSIG, &sigbits, &auto_sigbits, &ndis_event_count, ndis_events, ndis_args);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -