/* * ------------------------------------------------------------ * all_cachefstab_update * * Description: * Arguments: * Returns: * Preconditions: */ void all_cachefstab_update(cfsd_all_object_t *all_object_p) { cfsd_cache_object_t *cache_object_p; FILE *fout; dbug_enter("all_cachefstab_update"); fout = fopen(CACHEFSTAB, "w"); if (fout == NULL) { dbug_print(("error", "cannot write %s", CACHEFSTAB)); } else { cache_object_p = all_object_p->i_cachelist; while (cache_object_p != NULL) { dbug_assert(cache_object_p); fprintf(fout, "%s\n", cache_object_p->i_cachedir); cache_object_p = cache_object_p->i_next; } if (fclose(fout)) dbug_print(("error", "cannot close %s error %d", CACHEFSTAB, errno)); } dbug_leave("all_cachefstab_update"); }
/* Add a function to monitor socket */ LPSELECTDATA socket_poll_add (LPSELECTDATA lpSelectData, SELECTMODE EMode, HANDLE hFileDescr, LPVOID lpOrig) { LPSELECTDATA res; LPSELECTDATA hd; hd = lpSelectData; /* Polling socket can be done mulitple handle at the same time. You just need one worker to use it. Try to find if there is already a worker handling this kind of request. */ #ifdef DBUG dbug_print("Scanning list of worker to find one that already handle socket"); #endif res = select_data_job_search(&hd, SELECT_TYPE_SOCKET); /* Add a new socket to poll */ res->funcWorker = socket_poll; #ifdef DBUG dbug_print("Add socket %x to worker", hFileDescr); #endif select_data_query_add(res, EMode, hFileDescr, lpOrig); #ifdef DBUG dbug_print("Socket %x added", hFileDescr); #endif return hd; }
void worker_cleanup(void) { LPWORKER lpWorker = NULL; /* WARNING: we can have a race condition here, if while this code is executed another worker is waiting to access hWorkersMutex, he will never be able to get it... */ if (hWorkersMutex != INVALID_HANDLE_VALUE) { WaitForSingleObject(hWorkersMutex, INFINITE); #ifdef DBUG dbug_print("Freeing global resource of workers"); #endif /* Empty the queue of worker worker */ while (lpWorkers != NULL) { ReleaseMutex(hWorkersMutex); lpWorker = worker_pop(); #ifdef DBUG dbug_print("Freeing worker %x", lpWorker); #endif WaitForSingleObject(hWorkersMutex, INFINITE); worker_free(lpWorker); }; ReleaseMutex(hWorkersMutex); /* Destroy associated mutex */ CloseHandle(hWorkersMutex); hWorkersMutex = INVALID_HANDLE_VALUE; }; }
LPWORKER worker_job_submit (WORKERFUNC f, void *user_data) { LPWORKER lpWorker = worker_pop(); #ifdef DBUG dbug_print("Waiting for worker to be ready"); #endif enter_blocking_section(); WaitForSingleObject(lpWorker->hWorkerReady, INFINITE); ResetEvent(lpWorker->hWorkerReady); leave_blocking_section(); #ifdef DBUG dbug_print("Worker is ready"); #endif lpWorker->hJobFunc = f; lpWorker->lpJobUserData = user_data; lpWorker->ECommand = WORKER_CMD_EXEC; #ifdef DBUG dbug_print("Call worker (func: %x, worker: %x)", f, lpWorker); #endif SetEvent(lpWorker->hCommandReady); return (LPWORKER)lpWorker; }
/* Search for a job that has available query slots and that match provided type. * If none is found, create a new one. Return the corresponding SELECTDATA, and * update provided SELECTDATA head, if required. */ LPSELECTDATA select_data_job_search (LPSELECTDATA *lppSelectData, SELECTTYPE EType) { LPSELECTDATA res; res = NULL; /* Search for job */ #ifdef DBUG dbug_print("Searching an available job for type %d", EType); #endif res = *lppSelectData; while ( res != NULL && !( res->EType == EType && res->nQueriesCount < MAXIMUM_SELECT_OBJECTS ) ) { res = LIST_NEXT(LPSELECTDATA, res); } /* No matching job found, create one */ if (res == NULL) { #ifdef DBUG dbug_print("No job for type %d found, create one", EType); #endif res = select_data_new(*lppSelectData, EType); *lppSelectData = res; } return res; }
/* Monitor a pipe for input */ void read_pipe_poll (HANDLE hStop, void *_data) { DWORD event; DWORD n; LPSELECTQUERY iterQuery; LPSELECTDATA lpSelectData; DWORD i; /* Poll pipe */ event = 0; n = 0; lpSelectData = (LPSELECTDATA)_data; #ifdef DBUG dbug_print("Checking data pipe"); #endif while (lpSelectData->EState == SELECT_STATE_NONE) { for (i = 0; i < lpSelectData->nQueriesCount; i++) { iterQuery = &(lpSelectData->aQueries[i]); if (check_error( lpSelectData, PeekNamedPipe( iterQuery->hFileDescr, NULL, 0, NULL, &n, NULL) == 0)) { break; }; if (n > 0) { lpSelectData->EState = SELECT_STATE_SIGNALED; select_data_result_add(lpSelectData, iterQuery->EMode, iterQuery->lpOrig); }; }; /* Alas, nothing except polling seems to work for pipes. Check the state & stop_worker_event every 10 ms */ if (lpSelectData->EState == SELECT_STATE_NONE) { event = WaitForSingleObject(hStop, 10); if (event == WAIT_OBJECT_0 || check_error(lpSelectData, event == WAIT_FAILED)) { break; } } } #ifdef DBUG dbug_print("Finish checking data on pipe"); #endif }
void worker_job_stop (LPWORKER lpWorker) { #ifdef DBUG dbug_print("Sending stop signal to worker %x", lpWorker); #endif SetEvent(lpWorker->hJobStop); #ifdef DBUG dbug_print("Signal sent to worker %x", lpWorker); #endif }
/* * logfile_entry * * Description: * Sets addrp to the address of the log entry at offset * The mapping remains in effect until: * a) this routine is called again * b) logfile_teardown is called * c) this object is destroyed * Arguments: * offset offset to start of entry * entpp place to store address * Returns: * Returns 0 for success, 1 for EOF, -1 if a fatal error occurs. * Preconditions: * precond(addrp) */ int logfile_entry(cfsd_logfile_object_t *logfile_object_p, off_t offset, cfs_dlog_entry_t **entpp) { cfs_dlog_entry_t *entp; dbug_enter("logfile_entry"); dbug_precond(entpp); dbug_precond(offset >= sizeof (long)); logfile_object_p->i_stat_nextcnt++; /* check for eof */ if (offset >= logfile_object_p->i_size) { dbug_leave("logfile_entry"); return (1); } dbug_assert((offset & 3) == 0); /* get the address of the entry */ entp = (cfs_dlog_entry_t *)logfile_getaddr(logfile_object_p, offset, 0); if (entp == NULL) { dbug_leave("logfile_entry"); return (-1); } /* sanity check, record should be alligned */ if (entp->dl_len & 3) { dbug_print(("error", "Record at offset %d length is not alligned %d", offset, entp->dl_len)); dbug_leave("logfile_entry"); return (-1); } /* sanity check record should a reasonable size */ if ((entp->dl_len < CFS_DLOG_ENTRY_MINSIZE) || (entp->dl_len > CFS_DLOG_ENTRY_MAXSIZE)) { dbug_print(("error", "Record at offset %d has an invalid size %d", offset, entp->dl_len)); dbug_leave("logfile_entry"); return (-1); } /* preserve offset and pointer */ logfile_object_p->i_cur_offset = offset; logfile_object_p->i_cur_entry = entp; /* return success */ *entpp = entp; dbug_leave("logfile_entry"); return (0); }
/* * logfile_domap * * Description: * Maps in the specified section of the file. * Arguments: * off The offset to map in. Must be i_pagesize aligned. * map 0 means use map_entry, 1 means use map_offset * Returns: * Returns 0 for success or an errno value on failure. * Preconditions: */ int logfile_domap(cfsd_logfile_object_t *logfile_object_p, off_t off, int map) { int xx; int len; mmap_info_t *mmp; dbug_enter("logfile_domap"); dbug_precond(logfile_object_p->i_fid >= 0); len = logfile_object_p->i_maplen; mmp = (map == 0) ? &logfile_object_p->i_map_entry : &logfile_object_p->i_map_offset; logfile_object_p->i_stat_mapmove++; /* destroy old mapping if it exists */ if (mmp->i_pa) { /* determine how far we have to move the map */ logfile_object_p->i_stat_mapdist += abs(mmp->i_paoff - off); /* remove the map */ xx = munmap(mmp->i_pa, mmp->i_palen); if (xx == -1) { xx = errno; dbug_print(("error", "Could not unmap %s, %d, %p, %d", logfile_object_p->i_name, xx, mmp->i_pa, mmp->i_palen)); } mmp->i_pa = NULL; mmp->i_palen = 0; mmp->i_paoff = 0; mmp->i_paend = 0; } /* do the mapping */ mmp->i_pa = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, logfile_object_p->i_fid, off); if (mmp->i_pa == MAP_FAILED) { xx = errno; dbug_print(("error", "Could not map %s, error %d, off %d, len %d", logfile_object_p->i_name, xx, off, len)); mmp->i_pa = NULL; dbug_leave("logfile_domap"); return (xx); } mmp->i_palen = len; mmp->i_paoff = off; mmp->i_paend = off + len - 1; dbug_leave("logfile_domap"); return (0); }
/* * logfile_dumpstats * * Description: * Prints out various stats about the hashing. * Arguments: * Returns: * Preconditions: */ void logfile_dumpstats(cfsd_logfile_object_t *logfile_object_p) { int xx; double dd; dbug_enter("logfile_dumpstats"); dbug_print(("dump", "Request - next %d", logfile_object_p->i_stat_nextcnt)); dbug_print(("dump", "Request - offset %d", logfile_object_p->i_stat_offcnt)); dbug_print(("dump", "Map Moves %d", logfile_object_p->i_stat_mapmove)); dbug_print(("dump", "Mapping Size %d", logfile_object_p->i_maplen)); dbug_print(("dump", "Item Size %d", logfile_object_p->i_maxmap)); dbug_print(("dump", "File Size %d", logfile_object_p->i_size)); if (logfile_object_p->i_stat_mapmove == 0) { dbug_leave("logfile_dumpstats"); return; } dd = (double)logfile_object_p->i_stat_mapmove / (logfile_object_p->i_stat_nextcnt + logfile_object_p->i_stat_offcnt); dbug_print(("dump", "Mmap moves per Request %.2f", dd)); xx = logfile_object_p->i_stat_mapdist / logfile_object_p->i_stat_mapmove; dbug_print(("dump", "Average distance per mmap moves %d", xx)); dbug_leave("logfile_dumpstats"); }
/* * logfile_teardown * * Description: * Uninitializes the object. * Call logfile_setup before using this object again. * Arguments: * Returns: * Preconditions: */ void logfile_teardown(cfsd_logfile_object_t *logfile_object_p) { int xx; dbug_enter("logfile_teardown"); if (logfile_object_p->i_map_entry.i_pa) { xx = munmap(logfile_object_p->i_map_entry.i_pa, logfile_object_p->i_map_entry.i_palen); if (xx == -1) { xx = errno; dbug_print(("error", "Could not unmap %s, %d, %p, %d", logfile_object_p->i_name, xx, logfile_object_p->i_map_entry.i_pa, logfile_object_p->i_map_entry.i_palen)); } logfile_object_p->i_map_entry.i_pa = NULL; } logfile_object_p->i_map_entry.i_paoff = 0; logfile_object_p->i_map_entry.i_paend = 0; logfile_object_p->i_map_entry.i_palen = 0; if (logfile_object_p->i_map_offset.i_pa) { xx = munmap(logfile_object_p->i_map_offset.i_pa, logfile_object_p->i_map_offset.i_palen); if (xx == -1) { xx = errno; dbug_print(("error", "Could not unmap %s, %d, %p, %d", logfile_object_p->i_name, xx, logfile_object_p->i_map_offset.i_pa, logfile_object_p->i_map_offset.i_palen)); } logfile_object_p->i_map_offset.i_pa = NULL; } logfile_object_p->i_map_offset.i_paoff = 0; logfile_object_p->i_map_offset.i_paend = 0; logfile_object_p->i_map_offset.i_palen = 0; if (logfile_object_p->i_fid != -1) { if (close(logfile_object_p->i_fid)) dbug_print(("error", "Could not close %s, %d", logfile_object_p->i_name, errno)); logfile_object_p->i_fid = -1; } logfile_object_p->i_cur_offset = 0; logfile_object_p->i_cur_entry = NULL; dbug_leave("logfile_teardown"); }
/* Free select data */ void select_data_free (LPSELECTDATA lpSelectData) { DWORD i; #ifdef DBUG dbug_print("Freeing data of %x", lpSelectData); #endif /* Free APC related data, if they exists */ if (lpSelectData->lpWorker != NULL) { worker_job_finish(lpSelectData->lpWorker); lpSelectData->lpWorker = NULL; }; /* Make sure results/queries cannot be accessed */ lpSelectData->nResultsCount = 0; lpSelectData->nQueriesCount = 0; if (!HeapLock(GetProcessHeap())) { win32_maperr(GetLastError()); uerror("select_data_free", Nothing); }; HeapFree(GetProcessHeap(), 0, lpSelectData); HeapUnlock(GetProcessHeap()); }
/* * ----------------------------------------------------------------- * cfsd_fscache_destroy * * Description: * Arguments: * Returns: * Preconditions: */ void cfsd_fscache_destroy(cfsd_fscache_object_t *fscache_object_p) { int xx; dbug_enter("cfsd_fscache_destroy"); dbug_precond(fscache_object_p); /* dbug_assert(fscache_object_p->i_refcnt == 0); */ /* close down the message file descriptor */ if (fscache_object_p->i_ofd >= 0) { if (close(fscache_object_p->i_ofd)) dbug_print(("error", "cannot close fscache fd error %d", errno)); fscache_object_p->i_ofd = -1; } /* destroy the locking mutex */ xx = mutex_destroy(&fscache_object_p->i_lock); dbug_assert(xx == 0); /* destroy the conditional variable */ xx = cond_destroy(&fscache_object_p->i_cvwait); dbug_assert(xx == 0); cfsd_free(fscache_object_p); dbug_leave("cfsd_fscache_destroy"); }
uint8_t Connect_receive_IdReport( uint8_t id, uint16_t *pending_bytes, uint8_t uart_num ) { dbug_print("IdReport"); // Check the directionality if ( uart_num == UART_Master ) { erro_print("Invalid IdRequest direction..."); } // Track Id response if master if ( Connect_master ) { info_msg("Id Reported: "); printHex( id ); print( NL ); // Check if this is the highest ID if ( id > Connect_maxId ) Connect_maxId = id; return 1; } // Propagate id if yet another slave else { Connect_send_IdReport( id ); } return 1; }
uint8_t Connect_receive_IdEnumeration( uint8_t id, uint16_t *pending_bytes, uint8_t uart_num ) { dbug_print("IdEnumeration"); // Check the directionality if ( uart_num == UART_Slave ) { erro_print("Invalid IdEnumeration direction..."); } // Set the device id Connect_id = id; // Send reponse back to master Connect_send_IdReport( id ); // Node now enumerated, set current to last received current setting // Only set if this is not the master node if ( Connect_id != 0 ) { Output_update_external_current( Connect_LastCurrentValue ); } // Propogate next Id if the connection is ok if ( Connect_cableOkSlave ) { Connect_send_IdEnumeration( id + 1 ); } return 1; }
DWORD WINAPI worker_wait (LPVOID _data) { BOOL bExit; LPWORKER lpWorker; lpWorker = (LPWORKER )_data; bExit = FALSE; #ifdef DBUG dbug_print("Worker %x starting", lpWorker); #endif while ( !bExit && SignalObjectAndWait( lpWorker->hWorkerReady, lpWorker->hCommandReady, INFINITE, TRUE) == WAIT_OBJECT_0) { #ifdef DBUG dbug_print("Worker %x running", lpWorker); #endif switch (lpWorker->ECommand) { case WORKER_CMD_NONE: break; case WORKER_CMD_EXEC: if (lpWorker->hJobFunc != NULL) { SetEvent(lpWorker->hJobStarted); lpWorker->hJobFunc(lpWorker->hJobStop, lpWorker->lpJobUserData); SetEvent(lpWorker->hJobDone); }; break; case WORKER_CMD_STOP: bExit = TRUE; break; } }; #ifdef DBUG dbug_print("Worker %x exiting", lpWorker); #endif return 0; }
void cliFunc_connectCmd( char* args ) { // Parse number from argument // NOTE: Only first argument is used char* arg1Ptr; char* arg2Ptr; CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); print( NL ); switch ( numToInt( &arg1Ptr[0] ) ) { case CableCheck: Connect_send_CableCheck( UARTConnectCableCheckLength_define ); break; case IdRequest: Connect_send_IdRequest(); break; case IdEnumeration: Connect_send_IdEnumeration( 5 ); break; case IdReport: Connect_send_IdReport( 8 ); break; case ScanCode: { TriggerEvent scanCodes[] = { { 0x00, 0x01, 0x05 }, { 0x00, 0x03, 0x16 } }; Connect_send_ScanCode( 10, scanCodes, 2 ); break; } case Animation: break; case RemoteCapability: // TODO break; case RemoteOutput: // TODO break; case RemoteInput: // TODO break; case CurrentEvent: dbug_print("Sending current event"); Connect_send_CurrentEvent( 250 ); break; default: break; } }
int fscache_pingserver(cfsd_fscache_object_t *fscache_object_p) { static struct timeval TIMEOUT = { 25, 0 }; CLIENT *clnt; enum clnt_stat retval; int ret = 0; char hostname[sizeof (fscache_object_p->i_backfs)]; char *cptr; dbug_enter("fscache_pingserver"); dbug_precond(fscache_object_p); strlcpy(hostname, fscache_object_p->i_backfs, sizeof (hostname)); if (cptr = strchr(hostname, ':')) *cptr = '\0'; dbug_assert(cptr != NULL); dbug_print(("info", "remote host '%s' before clnt_create", hostname)); dbug_print(("info", "before clnt_create")); /* XXX this takes 75 seconds to time out */ /* XXX should use lower level routines to reduce overhead */ clnt = clnt_create(hostname, NFS_PROGRAM, NFS_VERSION, "udp"); if (clnt == NULL) { /* XXX what if this fails other than TIMEDOUT */ /* clnt_pcreateerror(hostname); */ dbug_print(("info", "clnt_create failed")); ret = -1; } else { dbug_print(("info", "before null rpc")); /* XXX this takes 45 seconds to time out */ retval = clnt_call(clnt, 0, xdr_void, NULL, xdr_void, NULL, TIMEOUT); if (retval != RPC_SUCCESS) { /* clnt_perror(clnt, "null rpc call failed"); */ dbug_print(("info", "null rpc call failed %d", retval)); ret = -1; } clnt_destroy(clnt); } dbug_leave("fscache_pingserver"); return (ret); }
/* * ------------------------------------------------------------ * cfsd_all_create * * Description: * Arguments: * Returns: * Preconditions: */ cfsd_all_object_t * cfsd_all_create(void) { /* get the host name */ struct utsname info; cfsd_all_object_t *all_object_p; int xx; char buffer[MAXPATHLEN]; dbug_enter("cfsd_all_create"); all_object_p = (cfsd_all_object_t *)cfsd_calloc(sizeof (cfsd_all_object_t)); xx = uname(&info); if (xx == -1) { dbug_print(("error", "cannot get host name")); strlcpy(all_object_p->i_machname, gettext("unknown"), sizeof (all_object_p->i_machname)); } else { strlcpy(all_object_p->i_machname, info.nodename, sizeof (all_object_p->i_machname)); } /* initialize the locking mutex */ xx = mutex_init(&all_object_p->i_lock, USYNC_THREAD, NULL); dbug_assert(xx == 0); all_object_p->i_nextcacheid = 0; all_object_p->i_modify = 1; all_object_p->i_cachelist = NULL; all_object_p->i_cachecount = 0; /* all_object_p->i_hoardp = NULL; */ snprintf(buffer, sizeof (buffer), gettext("host name is \"%s\""), all_object_p->i_machname); dbug_print(("info", buffer)); dbug_leave("cfsd_all_create"); return (all_object_p); }
void worker_job_finish (LPWORKER lpWorker) { #ifdef DBUG dbug_print("Finishing call of worker %x", lpWorker); #endif enter_blocking_section(); WaitForSingleObject(lpWorker->hJobDone, INFINITE); leave_blocking_section(); worker_push(lpWorker); }
void read_console_poll(HANDLE hStop, void *_data) { HANDLE events[2]; INPUT_RECORD record; DWORD waitRes; DWORD n; LPSELECTDATA lpSelectData; LPSELECTQUERY lpQuery; #ifdef DBUG dbug_print("Waiting for data on console"); #endif record; waitRes = 0; n = 0; lpSelectData = (LPSELECTDATA)_data; lpQuery = &(lpSelectData->aQueries[0]); events[0] = hStop; events[1] = lpQuery->hFileDescr; while (lpSelectData->EState == SELECT_STATE_NONE) { waitRes = WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitRes == WAIT_OBJECT_0 || check_error(lpSelectData, waitRes == WAIT_FAILED)) { /* stop worker event or error */ break; } /* console event */ if (check_error(lpSelectData, PeekConsoleInput(lpQuery->hFileDescr, &record, 1, &n) == 0)) { break; } /* check for ASCII keypress only */ if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown && record.Event.KeyEvent.uChar.AsciiChar != 0) { select_data_result_add(lpSelectData, lpQuery->EMode, lpQuery->lpOrig); lpSelectData->EState = SELECT_STATE_SIGNALED; break; } else { /* discard everything else and try again */ if (check_error(lpSelectData, ReadConsoleInput(lpQuery->hFileDescr, &record, 1, &n) == 0)) { break; } } }; }
void worker_push(LPWORKER lpWorker) { BOOL bFreeWorker; bFreeWorker = TRUE; WaitForSingleObject(hWorkersMutex, INFINITE); #ifdef DBUG dbug_print("Testing if we are under the maximum number of running workers"); #endif if (list_length((LPLIST)lpWorkers) < THREAD_WORKERS_MAX) { #ifdef DBUG dbug_print("Saving this worker for future use"); #endif #ifdef DBUG dbug_print("Next: %x", ((LPLIST)lpWorker)->lpNext); #endif lpWorkers = (LPWORKER)list_concat((LPLIST)lpWorker, (LPLIST)lpWorkers); bFreeWorker = FALSE; }; nWorkersCurrent--; #ifdef DBUG dbug_print("Workers running current/runnning max/waiting: %d/%d/%d", nWorkersCurrent, nWorkersMax, list_length((LPLIST)lpWorkers)); #endif ReleaseMutex(hWorkersMutex); if (bFreeWorker) { #ifdef DBUG dbug_print("Freeing worker %x", lpWorker); #endif worker_free(lpWorker); } }
void handle_set_add (LPSELECTHANDLESET hds, HANDLE hdl) { LPSELECTHANDLESET res; if (hds->nLast < hds->nMax) { hds->lpHdl[hds->nLast] = hdl; hds->nLast++; } #ifdef DBUG dbug_print("Adding handle %x to set %x", hdl, hds); #endif }
/* * logfile_sync * * Description: * Performs an fsync on the log file. * Arguments: * Returns: * Returns 0 for success or an errno value on failure. * Preconditions: */ int logfile_sync(cfsd_logfile_object_t *logfile_object_p) { int xx; dbug_enter("logfile_sync"); if (logfile_object_p->i_fid == -1) { dbug_leave("logfile_sync"); return (0); } xx = fsync(logfile_object_p->i_fid); if (xx) { xx = errno; dbug_print(("error", "fsync failed %d", xx)); } dbug_leave("logfile_sync"); return (xx); }
void worker_init (void) { int i = 0; /* Init a shared variable. The only way to ensure that no other worker will be at the same point is to use a critical section. */ #ifdef DBUG dbug_print("Allocating mutex for workers"); #endif if (hWorkersMutex == INVALID_HANDLE_VALUE) { hWorkersMutex = CreateMutex(NULL, FALSE, NULL); } if (hWorkerHeap == INVALID_HANDLE_VALUE) { hWorkerHeap = HeapCreate(0, sizeof(WORKER) * THREAD_WORKERS_MAX * 4, 0); } }
/* Add a function to monitor pipe input */ LPSELECTDATA read_pipe_poll_add (LPSELECTDATA lpSelectData, SELECTMODE EMode, HANDLE hFileDescr, LPVOID lpOrig) { LPSELECTDATA res; LPSELECTDATA hd; hd = lpSelectData; /* Polling pipe is a non blocking operation by default. This means that each worker can handle many pipe. We begin to try to find a worker that is polling pipe, but for which there is under the limit of pipe per worker. */ #ifdef DBUG dbug_print("Searching an available worker handling pipe"); #endif res = select_data_job_search(&hd, SELECT_TYPE_PIPE_READ); /* Add a new pipe to poll */ res->funcWorker = read_pipe_poll; select_data_query_add(res, EMode, hFileDescr, lpOrig); return hd; }
LPWORKER worker_pop (void) { LPWORKER lpWorkerFree = NULL; WaitForSingleObject(hWorkersMutex, INFINITE); /* Get the first worker of the list */ if (lpWorkers != NULL) { lpWorkerFree = lpWorkers; lpWorkers = LIST_NEXT(LPWORKER, lpWorkers); } nWorkersCurrent++; nWorkersMax = (nWorkersCurrent > nWorkersMax ? nWorkersCurrent : nWorkersMax); #ifdef DBUG dbug_print("Workers running current/runnning max/waiting: %d/%d/%d", nWorkersCurrent, nWorkersMax, list_length((LPLIST)lpWorkers)); #endif ReleaseMutex(hWorkersMutex); if (lpWorkerFree == NULL) { /* We cannot find a free worker, create one. */ lpWorkerFree = worker_new(); } /* Ensure that we don't get dangling pointer to old data. */ list_init((LPLIST)lpWorkerFree); lpWorkerFree->lpJobUserData = NULL; /* Reset events */ ResetEvent(lpWorkerFree->hJobStarted); ResetEvent(lpWorkerFree->hJobStop); ResetEvent(lpWorkerFree->hJobDone); return lpWorkerFree; }
uint8_t Connect_receive_IdEnumeration( uint8_t id, uint16_t *pending_bytes, uint8_t uart_num ) { dbug_print("IdEnumeration"); // Check the directionality if ( uart_num == UART_Slave ) { erro_print("Invalid IdEnumeration direction..."); } // Set the device id Connect_id = id; // Send reponse back to master Connect_send_IdReport( id ); // Propogate next Id if the connection is ok if ( Connect_cableOkSlave ) { Connect_send_IdEnumeration( id + 1 ); } return 1; }
void LED_readPage( uint8_t len, uint8_t page ) { // Software shutdown must be enabled to read registers LED_writeReg( 0x0A, 0x00, 0x0B ); // Page Setup uint8_t pageSetup[] = { 0xE8, 0xFD, page }; // Setup page while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 ) delay(1); // Register Setup uint8_t regSetup[] = { 0xE8, 0x00 }; // Read each register in the page for ( uint8_t reg = 0; reg < len; reg++ ) { // Update register to read regSetup[1] = reg; // Configure register while ( I2C_Send( regSetup, sizeof( regSetup ), 0 ) == 0 ) delay(1); // Register Read Command uint8_t regReadCmd[] = { 0xE9 }; // Request single register byte while ( I2C_Send( regReadCmd, sizeof( regReadCmd ), 1 ) == 0 ) delay(1); dbug_print("NEXT"); } // Disable software shutdown LED_writeReg( 0x0A, 0x01, 0x0B ); }
uint8_t Connect_receive_IdRequest( uint8_t byte, uint16_t *pending_bytes, uint8_t uart_num ) { dbug_print("IdRequest"); // Check the directionality if ( uart_num == UART_Master ) { erro_print("Invalid IdRequest direction..."); } // Check if master, begin IdEnumeration if ( Connect_master ) { // The first device is always id 1 // Id 0 is reserved for the master Connect_send_IdEnumeration( 1 ); } // Propagate IdRequest else { Connect_send_IdRequest(); } return 1; }