globus_result_t globus_i_xio_win32_complete( globus_callback_func_t callback, void * user_arg) { globus_l_xio_win32_poll_entry_t * entry; globus_result_t result; GlobusXIOName(globus_i_xio_win32_complete); GlobusXIOSystemDebugEnter(); if (! globus_i_am_only_thread()) { return globus_callback_register_oneshot( 0, 0, callback, user_arg); } win32_mutex_lock(&globus_l_xio_win32_poll_lock); { if(globus_l_xio_win32_poll_free) { entry = globus_l_xio_win32_poll_free; globus_l_xio_win32_poll_free = entry->next; } else { entry = (globus_l_xio_win32_poll_entry_t *) globus_malloc(sizeof(globus_l_xio_win32_poll_entry_t)); if(!entry) { result = GlobusXIOErrorMemory("entry"); goto error_malloc; } } entry->callback = callback; entry->user_arg = user_arg; GlobusLWin32PollQueueEnqueue(entry); if(globus_l_xio_win32_poll_event_sleeping && !globus_l_xio_win32_poll_event_pending) { SetEvent(globus_l_xio_win32_poll_event); globus_l_xio_win32_poll_event_pending = GLOBUS_TRUE; } } win32_mutex_unlock(&globus_l_xio_win32_poll_lock); GlobusXIOSystemDebugExit(); return GLOBUS_SUCCESS; error_malloc: return result; }
void cc_mutex_lock(cc_mutex * mutex) { int ok; SbBool timeit; cc_time start = 0.0; assert(mutex != NULL); timeit = (maxmutexlocktime != DBL_MAX) || (reportmutexlocktiming != DBL_MAX); if (timeit) { start = cc_time_gettimeofday(); } #ifdef USE_W32THREAD ok = cc_mutex_TryEnterCriticalSection ? win32_cs_lock(mutex) : win32_mutex_lock(mutex); #else /* USE_W32THREAD */ ok = internal_mutex_lock(mutex); #endif /* USE_W32THREAD */ assert(ok == CC_OK); /* This is here as an optional debugging aid, when having problems related to locks that are held too long. (Typically resulting in unresponsive user interaction / lags.) */ if (timeit) { const cc_time spent = cc_time_gettimeofday() - start; if (spent >= reportmutexlocktiming) { /* Can't use cc_debugerror_postinfo() here, because we get a recursive call to this function, and a non-terminating lock / hang. */ (void)fprintf(stdout, "DEBUG cc_mutex_lock(): mutex %p spent %f secs in lock\n", mutex, spent); } assert(spent <= maxmutexlocktime); } }
static globus_result_t globus_l_xio_win32_socket_register_write( globus_l_xio_win32_socket_t * handle, globus_i_xio_system_op_info_t * write_info) { globus_result_t result; GlobusXIOName(globus_l_xio_win32_socket_register_write); GlobusXIOSystemDebugEnterFD(handle->socket); /* I have to do this outside the lock because of lock inversion issues */ if(write_info->op && globus_xio_operation_enable_cancel( write_info->op, globus_l_xio_win32_socket_cancel_cb, write_info)) { result = GlobusXIOErrorCanceled(); goto error_cancel_enable; } win32_mutex_lock(&handle->lock); { if(write_info->state == GLOBUS_I_XIO_SYSTEM_OP_CANCELED) { result = globus_error_put(write_info->error); goto error_canceled; } if(handle->write_info) { result = GlobusXIOErrorAlreadyRegistered(); goto error_already_registered; } write_info->state = GLOBUS_I_XIO_SYSTEM_OP_PENDING; /* if select() functionality requested, only handle after we receive * write event * * also dont call for connect operations. waitforbytes == 0 in this * case and handle->ready_events should not yet have a write event */ if(write_info->waitforbytes > 0 || handle->ready_events & FD_WRITE) { globus_l_xio_win32_socket_handle_write(handle, write_info); } if(write_info->state != GLOBUS_I_XIO_SYSTEM_OP_COMPLETE) { /* make sure we're set up to be notified of events */ long needevents; if(write_info->type == GLOBUS_I_XIO_SYSTEM_OP_CONNECT) { needevents = FD_CONNECT|FD_CLOSE; } else { needevents = FD_WRITE|FD_CLOSE; } if((handle->eventselect & needevents) != needevents) { if(WSAEventSelect( handle->socket, handle->event, handle->eventselect|needevents) == SOCKET_ERROR) { write_info->error = GlobusXIOErrorObjSystemError( "WSAEventSelect", WSAGetLastError()); } else { handle->eventselect |= needevents; } } if(!write_info->error) { handle->write_info = write_info; write_info = 0; } } } win32_mutex_unlock(&handle->lock); /* do this outside the lock to avoid unnecessary contention */ if(write_info) { globus_l_xio_win32_socket_complete(write_info, GLOBUS_FALSE); } GlobusXIOSystemDebugExitFD(handle->socket); return GLOBUS_SUCCESS; error_already_registered: error_canceled: write_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE; win32_mutex_unlock(&handle->lock); if(write_info->op) { globus_xio_operation_disable_cancel(write_info->op); } error_cancel_enable: GlobusXIOSystemDebugExitWithErrorFD(handle->socket); return result; }
/* always called from win32 thread */ static globus_bool_t globus_l_xio_win32_socket_event_cb( void * user_arg) { globus_l_xio_win32_socket_t * handle; WSANETWORKEVENTS wsaevents; long events; long clearevents = 0; globus_i_xio_system_op_info_t * read_info = 0; globus_i_xio_system_op_info_t * write_info = 0; GlobusXIOName(globus_l_xio_win32_socket_event_cb); handle = (globus_l_xio_win32_socket_t *) user_arg; GlobusXIOSystemDebugEnterFD(handle->socket); if(WSAEnumNetworkEvents( handle->socket, handle->event, &wsaevents) == SOCKET_ERROR) { GlobusXIOSystemDebugSysError( "WSAEnumNetworkEvents error", WSAGetLastError()); goto error_enum; } events = wsaevents.lNetworkEvents; win32_mutex_lock(&handle->lock); { GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_INFO, ("[%s] Ready events: %s%s%s%s%s fd=%lu\n", _xio_name, events & FD_ACCEPT ? "accept;" : "", events & FD_CONNECT ? "connect;" : "", events & FD_READ ? "read;" : "", events & FD_WRITE ? "write;" : "", events & FD_CLOSE ? "close;" : "", (unsigned long)handle->socket)); if(events & (FD_ACCEPT|FD_READ|FD_CLOSE)) { /* cache for select() like functionality */ handle->ready_events |= FD_READ; if(handle->read_info) { globus_l_xio_win32_socket_handle_read( handle, handle->read_info); if(handle->read_info->state == GLOBUS_I_XIO_SYSTEM_OP_COMPLETE) { read_info = handle->read_info; handle->read_info = 0; } } else { clearevents |= FD_ACCEPT|FD_READ; } } if(events & (FD_CONNECT|FD_WRITE|FD_CLOSE)) { /* cache for select() like functionality */ handle->ready_events |= FD_WRITE; if(handle->write_info) { globus_l_xio_win32_socket_handle_write( handle, handle->write_info); if(handle->write_info->state == GLOBUS_I_XIO_SYSTEM_OP_COMPLETE) { write_info = handle->write_info; handle->write_info = 0; } } else { clearevents |= FD_CONNECT|FD_WRITE; } } /* clear any events we want to ignore */ if((handle->eventselect & clearevents)) { handle->eventselect &= ~clearevents; WSAEventSelect(handle->socket, handle->event, handle->eventselect); } } win32_mutex_unlock(&handle->lock); /* do this outside the lock to avoid unnecessary contention */ if(read_info) { globus_l_xio_win32_socket_complete(read_info, GLOBUS_TRUE); } if(write_info) { globus_l_xio_win32_socket_complete(write_info, GLOBUS_TRUE); } GlobusXIOSystemDebugExitFD(handle->socket); return GLOBUS_TRUE; error_enum: GlobusXIOSystemDebugExitWithErrorFD(handle->socket); return GLOBUS_TRUE; }
static void globus_l_xio_win32_socket_cancel_cb( globus_xio_operation_t op, void * user_arg, globus_xio_error_type_t reason) { globus_i_xio_system_op_info_t * op_info; GlobusXIOName(globus_l_xio_win32_socket_cancel_cb); GlobusXIOSystemDebugEnter(); op_info = (globus_i_xio_system_op_info_t *) user_arg; /* this access of the handle is not safe if users destroy it * with outstanding callbacks. I don't think that is allowed, so we * should be ok. */ win32_mutex_lock(&op_info->handle->lock); { if(op_info->state != GLOBUS_I_XIO_SYSTEM_OP_COMPLETE && op_info->state != GLOBUS_I_XIO_SYSTEM_OP_CANCELED) { op_info->error = reason == GLOBUS_XIO_ERROR_TIMEOUT ? GlobusXIOErrorObjTimeout() : GlobusXIOErrorObjCanceled(); if(op_info->state == GLOBUS_I_XIO_SYSTEM_OP_NEW) { op_info->state = GLOBUS_I_XIO_SYSTEM_OP_CANCELED; GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_INFO, ("[%s] fd=%lu, Canceling NEW\n", _xio_name, (unsigned long)op_info->handle->socket)); } else { globus_result_t result; op_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE; GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_INFO, ("[%s] fd=%lu, Canceling Pending\n", _xio_name, (unsigned long)op_info->handle->socket)); if(op_info->handle->read_info == op_info) { op_info->handle->read_info = 0; } else { globus_assert(op_info->handle->write_info == op_info); op_info->handle->write_info = 0; } /* unregister and kickout now */ result = globus_callback_register_oneshot( 0, 0, globus_l_xio_win32_socket_kickout, op_info); /* really cant do anything else */ if(result != GLOBUS_SUCCESS) { globus_panic( GLOBUS_XIO_SYSTEM_MODULE, result, _XIOSL("[%s:%d] Couldn't register callback"), _xio_name, __LINE__); } } } } win32_mutex_unlock(&op_info->handle->lock); GlobusXIOSystemDebugExit(); }
globus_result_t globus_xio_system_socket_write( globus_xio_system_socket_handle_t handle, const globus_xio_iovec_t * iov, int iovc, globus_size_t waitforbytes, int flags, globus_sockaddr_t * to, globus_size_t * nbytes) { globus_result_t result; globus_l_xio_win32_blocking_info_t * blocking_info; GlobusXIOName(globus_xio_system_socket_write); GlobusXIOSystemDebugEnterFD(handle->socket); GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_DATA, ("[%s] Waiting for %ld bytes\n", _xio_name, (long) waitforbytes)); win32_mutex_lock(&handle->lock); { result = globus_i_xio_system_socket_try_write( handle->socket, iov, iovc, flags, to, nbytes); } win32_mutex_unlock(&handle->lock); if(result == GLOBUS_SUCCESS && *nbytes < waitforbytes) { result = globus_l_xio_win32_blocking_init(&blocking_info); if(result != GLOBUS_SUCCESS) { result = GlobusXIOErrorWrapFailed( "globus_l_xio_win32_blocking_init", result); goto error_init; } result = globus_l_xio_system_socket_register_write( 0, handle, iov, iovc, waitforbytes, *nbytes, flags, to, globus_l_xio_win32_blocking_cb, blocking_info); if(result != GLOBUS_SUCCESS) { result = GlobusXIOErrorWrapFailed( "globus_l_xio_system_socket_register_write", result); goto error_register; } while(WaitForSingleObject( blocking_info->event, INFINITE) != WAIT_OBJECT_0) {} if(blocking_info->error) { result = globus_error_put(blocking_info->error); } *nbytes = blocking_info->nbytes; globus_l_xio_win32_blocking_destroy(blocking_info); } GlobusXIOSystemDebugExitFD(handle->socket); return result; error_register: globus_l_xio_win32_blocking_destroy(blocking_info); error_init: GlobusXIOSystemDebugExitWithErrorFD(handle->socket); return result; }
static void globus_l_xio_win32_poll( void * user_arg) { GlobusXIOName(globus_l_xio_win32_poll); GlobusXIOSystemDebugEnter(); win32_mutex_lock(&globus_l_xio_win32_poll_lock); { if(GlobusLWin32PollQueueEmpty()) { globus_reltime_t time_left; globus_callback_get_timeout(&time_left); if(globus_reltime_cmp(&time_left, &globus_i_reltime_zero) > 0) { DWORD millis = INFINITE; if(!globus_time_reltime_is_infinity(&time_left)) { GlobusTimeReltimeToMilliSec(millis, time_left); } globus_l_xio_win32_poll_event_sleeping = GLOBUS_TRUE; win32_mutex_unlock(&globus_l_xio_win32_poll_lock); WaitForSingleObject(globus_l_xio_win32_poll_event, millis); win32_mutex_lock(&globus_l_xio_win32_poll_lock); globus_l_xio_win32_poll_event_sleeping = GLOBUS_FALSE; globus_l_xio_win32_poll_event_pending = GLOBUS_FALSE; } } while(!GlobusLWin32PollQueueEmpty()) { globus_l_xio_win32_poll_entry_t * entry; GlobusLWin32PollQueueDequeue(entry); win32_mutex_unlock(&globus_l_xio_win32_poll_lock); entry->callback(entry->user_arg); win32_mutex_lock(&globus_l_xio_win32_poll_lock); entry->next = globus_l_xio_win32_poll_free; globus_l_xio_win32_poll_free = entry; if(globus_callback_has_time_expired()) { break; } } } win32_mutex_unlock(&globus_l_xio_win32_poll_lock); GlobusXIOSystemDebugExit(); }