int_t select(int_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const timeval *timeout) { int_t i; int_t j; int_t n; int_t s; time_t time; uint_t eventMask; uint_t eventFlags; OsEvent *event; fd_set *fds; //Create an event object to get notified of socket events event = osEventCreate(FALSE, FALSE); //Any error to report? if(event == OS_INVALID_HANDLE) { socketError(NULL, ERROR_OUT_OF_RESOURCES); return SOCKET_ERROR; } //Parse all the descriptor sets for(i = 0; i < 3; i ++) { //Select the suitable descriptor set switch(i) { case 0: //Set of sockets to be checked for readability fds = readfds; eventMask = SOCKET_EVENT_RX_READY; break; case 1: //Set of sockets to be checked for writability fds = writefds; eventMask = SOCKET_EVENT_TX_READY; break; default: //Set of sockets to be checked for errors fds = exceptfds; eventMask = SOCKET_EVENT_CLOSED; break; } //Each descriptor is optional and may be omitted if(fds != NULL) { //Parse the current set of sockets for(j = 0; j < fds->fd_count; j++) { //Get the descriptor associated with the current entry s = fds->fd_array[j]; //Subscribe to the requested events socketRegisterEvents(&socketTable[s], event, eventMask); } } } //Retrieve timeout value if(timeout != NULL) time = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; else time = INFINITE_DELAY; //Block the current task until an event occurs osEventWait(event, time); //Count the number of events in the signaled state n = 0; //Parse all the descriptor sets for(i = 0; i < 3; i ++) { //Select the suitable descriptor set switch(i) { case 0: //Set of sockets to be checked for readability fds = readfds; eventMask = SOCKET_EVENT_RX_READY; break; case 1: //Set of sockets to be checked for writability fds = writefds; eventMask = SOCKET_EVENT_TX_READY; break; default: //Set of sockets to be checked for errors fds = exceptfds; eventMask = SOCKET_EVENT_CLOSED; break; } //Each descriptor is optional and may be omitted if(fds != NULL) { //Parse the current set of sockets for(j = 0; j < fds->fd_count; ) { //Get the descriptor associated with the current entry s = fds->fd_array[j]; //Retrieve event flags for the current socket socketGetEvents(&socketTable[s], &eventFlags); //Unsubscribe previously registered events socketUnregisterEvents(&socketTable[s]); //Event flag is set? if(eventFlags & eventMask) { //Track the number of events in the signaled state n++; //Jump to the next socket descriptor j++; } else { //Remove descriptor from the current set selectFdClr(fds, s); } } } } //Close event osEventClose(event); //Return the number of events in the signaled state return n; }
error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent, systime_t timeout) { uint_t i; bool_t status; OsEvent *event; OsEvent eventObject; //Check parameters if(!eventDesc || !size) return ERROR_INVALID_PARAMETER; //Try to use the supplied event object to receive notifications if(!extEvent) { //Create an event object only if necessary if(!osCreateEvent(&eventObject)) { //Report an error return ERROR_OUT_OF_RESOURCES; } //Reference to the newly created event event = &eventObject; } else { //Reference to the external event event = extEvent; } //Loop through descriptors for(i = 0; i < size; i++) { //Clear event flags eventDesc[i].eventFlags = 0; //Subscribe to the requested events socketRegisterEvents(eventDesc[i].socket, event, eventDesc[i].eventMask); } //Block the current task until an event occurs status = osWaitForEvent(event, timeout); //Any socket event is in the signaled state? if(status) { //Loop through descriptors for(i = 0; i < size; i++) { //Retrieve event flags for the current socket socketGetEvents(eventDesc[i].socket, &eventDesc[i].eventFlags); //Clear unnecessary flags eventDesc[i].eventFlags &= eventDesc[i].eventMask; } } //Unsubscribe previously registered events for(i = 0; i < size; i++) socketUnregisterEvents(eventDesc[i].socket); //Reset event object before exiting... osResetEvent(event); //Release previously allocated resources if(!extEvent) osDeleteEvent(&eventObject); //Return status code return status ? NO_ERROR : ERROR_TIMEOUT; }