//------------------------------------------------------------------------------ // // Function: UpdatePeriod // VOID UpdatePeriod( UINT32 periodMSec ) { UINT32 period, match; INT32 delta; UINT64 offsetMSec = periodMSec; UINT64 tickCount = OALGetTickCount(); INT nDelay; // Calculate count difference period = (UINT32)MSEC_TO_TICK(offsetMSec); nDelay = min(period, DELTA_TIME); // This is compare value match = ((UINT32)MSEC_TO_TICK(tickCount)) + nDelay; delta = (INT32)(OALTimerGetCount()+ g_oalTimerContext.margin - match); // If we are behind, issue interrupt as soon as possible if (delta > 0) { match += MSEC_TO_TICK(1); } // Save off match value g_oalTimerContext.match = match; // Set timer match value OALTimerSetCompare(match); }
/*FUNCTION********************************************************************** * * Function Name : OSA_SemaphoreWait * Description : This function checks the semaphore's counting value, if it is * positive, decreases it and returns osaStatus_Success, otherwise, timeout * will be used for wait. The parameter timeout indicates how long should wait * in milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will * return osaStatus_Timeout immediately if semaphore is not positive. * This function returns osaStatus_Success if the semaphore is received, returns * osaStatus_Timeout if the semaphore is not received within the specified * 'timeout', returns osaStatus_Error if any errors occur during waiting. * *END**************************************************************************/ osaStatus_t OSA_SemaphoreWait(osaSemaphoreId_t semId, uint32_t millisec) { #if osNumberOfSemaphores uint32_t timeoutTicks; if(semId == NULL) { return osaStatus_Error; } semaphore_t sem = (semaphore_t)semId; /* Convert timeout from millisecond to tick. */ if (millisec == osaWaitForever_c) { timeoutTicks = portMAX_DELAY; } else { timeoutTicks = MSEC_TO_TICK(millisec); } if (xSemaphoreTake(sem, timeoutTicks)==pdFALSE) { return osaStatus_Timeout; /* timeout */ } else { return osaStatus_Success; /* semaphore taken */ } #else (void)semId; (void)millisec; return osaStatus_Error; #endif }
/*FUNCTION********************************************************************** * * Function Name : OSA_MutexLock * Description : This function checks the mutex's status, if it is unlocked, * lock it and returns kStatus_OSA_Success, otherwise, timeout will be used for * wait. The parameter timeout indicates how long should wait in milliseconds. * Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will return the value * kStatus_OSA_Timeout immediately if mutex is locked. * This function returns kStatus_OSA_Success if the mutex is obtained, returns * kStatus_OSA_Timeout if the mutex is not obtained within the specified * 'timeout', returns kStatus_OSA_Error if any errors occur during waiting. * *END**************************************************************************/ osa_status_t OSA_MutexLock(mutex_t *pMutex, uint32_t timeout) { uint32_t timeoutTicks; assert(pMutex); /* If pMutex has been locked by current task, return error. */ if (xSemaphoreGetMutexHolder(*pMutex) == xTaskGetCurrentTaskHandle()) { return kStatus_OSA_Error; } /* Convert timeout from millisecond to tick. */ if (timeout == OSA_WAIT_FOREVER) { timeoutTicks = portMAX_DELAY; } else { timeoutTicks = MSEC_TO_TICK(timeout); } if (xSemaphoreTake(*pMutex, timeoutTicks)==pdFALSE) { return kStatus_OSA_Timeout; /* timeout */ } else { return kStatus_OSA_Success; /* semaphore taken */ } }
/* * Timeout function to reset the SCTP stack variable sctps_reclaim to false. */ static void sctp_reclaim_timer(void *arg) { sctp_stack_t *sctps = (sctp_stack_t *)arg; int64_t tot_assoc = 0; int i; extern pgcnt_t lotsfree, needfree; for (i = 0; i < sctps->sctps_sc_cnt; i++) tot_assoc += sctps->sctps_sc[i]->sctp_sc_assoc_cnt; /* * This happens only when a stack is going away. sctps_reclaim_tid * should not be reset to 0 when returning in this case. */ mutex_enter(&sctps->sctps_reclaim_lock); if (!sctps->sctps_reclaim) { mutex_exit(&sctps->sctps_reclaim_lock); return; } if ((freemem >= lotsfree + needfree) || tot_assoc < maxusers) { sctps->sctps_reclaim = B_FALSE; sctps->sctps_reclaim_tid = 0; } else { /* Stay in defensive mode and restart the timer */ sctps->sctps_reclaim_tid = timeout(sctp_reclaim_timer, sctps, MSEC_TO_TICK(sctps->sctps_reclaim_period)); } mutex_exit(&sctps->sctps_reclaim_lock); }
/*FUNCTION********************************************************************** * * Function Name : OSA_MsgQGet * Description : This function checks the queue's status, if it is not empty, * get message from it and return osaStatus_Success, otherwise, timeout will * be used for wait. The parameter timeout indicates how long should wait in * milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will return * osaStatus_Timeout immediately if queue is empty. * This function returns osaStatus_Success if message is got successfully, * returns osaStatus_Timeout if message queue is empty within the specified * 'timeout', returns osaStatus_Error if any errors occur during waiting. * *END**************************************************************************/ osaStatus_t OSA_MsgQGet(osaMsgQId_t msgQId, void *pMessage, uint32_t millisec) { #if osNumberOfMessageQs osaStatus_t osaStatus; msg_queue_handler_t handler; uint32_t timeoutTicks; if( msgQId == NULL ) { return osaStatus_Error; } handler = (msg_queue_handler_t)msgQId; if (millisec == osaWaitForever_c) { timeoutTicks = portMAX_DELAY; } else { timeoutTicks = MSEC_TO_TICK(millisec); } if (xQueueReceive(handler, pMessage, timeoutTicks)!=pdPASS) { osaStatus = osaStatus_Timeout; /* not able to send it to the queue? */ } else { osaStatus = osaStatus_Success; } return osaStatus; #else (void)msgQId; (void)pMessage; (void)millisec; return osaStatus_Error; #endif }
/* * Retry opens to avoid spurious sharing violations, due to timing * issues between closes and opens. The client that already has the * file open may be in the process of closing it. */ uint32_t smb_common_open(smb_request_t *sr) { smb_arg_open_t *parg; uint32_t status = NT_STATUS_SUCCESS; int count; parg = kmem_alloc(sizeof (*parg), KM_SLEEP); bcopy(&sr->arg.open, parg, sizeof (*parg)); for (count = 0; count <= 4; count++) { if (count != 0) delay(MSEC_TO_TICK(400)); status = smb_open_subr(sr); if (status != NT_STATUS_SHARING_VIOLATION) break; bcopy(parg, &sr->arg.open, sizeof (*parg)); } if (status == NT_STATUS_SHARING_VIOLATION) { smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); } if (status == NT_STATUS_NO_SUCH_FILE) { smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERROR_FILE_NOT_FOUND); } kmem_free(parg, sizeof (*parg)); return (status); }
/*FUNCTION********************************************************************** * * Function Name : OSA_TimeDelay * Description : This function is used to delay for a number of milliseconds. * *END**************************************************************************/ void OSA_TimeDelay(uint32_t delay) { delay = MSEC_TO_TICK(delay); /* * If delay is too short that changed to 0 tick, reset it to 1 tick * in case of no delay. */ if (!delay) { delay = 1U; } OSTimeDly(delay); }
//------------------------------------------------------------------------------ // // Function: OALTimerUpdateRescheduleTime // // This function is called by kernel to set next reschedule time. // VOID OALTimerUpdateRescheduleTime( DWORD timeMSec ) { UINT32 baseMSec, periodMSec; INT32 delta; // Get current system timer counter baseMSec = CurMSec; // How far we are from next tick delta = (INT32)(g_oalTimerContext.match - OALTimerGetCount()); if( delta < 0 ) { UpdatePeriod(0); goto cleanUp; } // If timer interrupts occurs, or we are within 1 ms of the scheduled // interrupt, just return - timer ISR will take care of it. if ((baseMSec != CurMSec) || (delta < MSEC_TO_TICK(1))) goto cleanUp; // Calculate the distance between the new time and the last timer interrupt periodMSec = timeMSec - OEMGetTickCount(); // Trying to set reschedule time prior or equal to CurMSec - this could // happen if a thread is on its way to sleep while preempted before // getting into the Sleep Queue if ((INT32)periodMSec < 0) { periodMSec = 0; } else if (periodMSec > g_oalTimerContext.maxPeriodMSec) { periodMSec = g_oalTimerContext.maxPeriodMSec; } // Now we find new period, so update timer UpdatePeriod(periodMSec); cleanUp: return; }
/*FUNCTION********************************************************************** * * Function Name : wait_timeout_msec_to_tick * Description : This function converts timeout from millisecond to tick for * wait functions. * *END**************************************************************************/ static uint32_t wait_timeout_msec_to_tick(uint32_t timeout) { if (OSA_WAIT_FOREVER == timeout) /* Wait forever. */ { return 0U; /* Timeout 0 means wait forever for uC/OS-II. */ } else { timeout = MSEC_TO_TICK(timeout); /* Change timeout to tick. */ /* * If timeout is too short that changed to 0 tick, reset it to 1 tick * in case of infinitely wait. */ if (!timeout) { timeout = 1U; } return timeout; } }
/*FUNCTION********************************************************************** * * Function Name : OSA_MutexLock * Description : This function checks the mutex's status, if it is unlocked, * lock it and returns osaStatus_Success, otherwise, wait for the mutex. * This function returns osaStatus_Success if the mutex is obtained, returns * osaStatus_Error if any errors occur during waiting. If the mutex has been * locked, pass 0 as timeout will return osaStatus_Timeout immediately. * *END**************************************************************************/ osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec) { #if osNumberOfMutexes uint32_t timeoutTicks; mutex_t mutex = (mutex_t)mutexId; if(mutexId == NULL) { return osaStatus_Error; } /* If pMutex has been locked by current task, return error. */ if (xSemaphoreGetMutexHolder(mutex) == xTaskGetCurrentTaskHandle()) { return osaStatus_Error; } /* Convert timeout from millisecond to tick. */ if (millisec == osaWaitForever_c) { timeoutTicks = portMAX_DELAY; } else { timeoutTicks = MSEC_TO_TICK(millisec); } if (xSemaphoreTake(mutex, timeoutTicks)==pdFALSE) { return osaStatus_Timeout; /* timeout */ } else { return osaStatus_Success; /* semaphore taken */ } #else (void)mutexId; (void)millisec; return osaStatus_Error; #endif }
/*FUNCTION********************************************************************** * * Function Name : OSA_MsgQGet * Description : This function checks the queue's status, if it is not empty, * get message from it and return kStatus_OSA_Success, otherwise, timeout will * be used for wait. The parameter timeout indicates how long should wait in * milliseconds. Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will return * kStatus_OSA_Timeout immediately if queue is empty. * This function returns kStatus_OSA_Success if message is got successfully, * returns kStatus_OSA_Timeout if message queue is empty within the specified * 'timeout', returns kStatus_OSA_Error if any errors occur during waiting. * *END**************************************************************************/ osa_status_t OSA_MsgQGet(msg_queue_handler_t handler, void *pMessage, uint32_t timeout) { uint32_t timeoutTicks; if (timeout == OSA_WAIT_FOREVER) { timeoutTicks = portMAX_DELAY; } else { timeoutTicks = MSEC_TO_TICK(timeout); } if (xQueueReceive(handler, pMessage, timeoutTicks)!=pdPASS) { return kStatus_OSA_Timeout; /* not able to send it to the queue? */ } else { return kStatus_OSA_Success; } }
/*FUNCTION********************************************************************** * * Function Name : OSA_SemaWait * Description : This function checks the semaphore's counting value, if it is * positive, decreases it and returns kStatus_OSA_Success, otherwise, timeout * will be used for wait. The parameter timeout indicates how long should wait * in milliseconds. Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will * return kStatus_OSA_Timeout immediately if semaphore is not positive. * This function returns kStatus_OSA_Success if the semaphore is received, returns * kStatus_OSA_Timeout if the semaphore is not received within the specified * 'timeout', returns kStatus_OSA_Error if any errors occur during waiting. * *END**************************************************************************/ osa_status_t OSA_SemaWait(semaphore_t *pSem, uint32_t timeout) { uint32_t timeoutTicks; assert(pSem); /* Convert timeout from millisecond to tick. */ if (timeout == OSA_WAIT_FOREVER) { timeoutTicks = portMAX_DELAY; } else { timeoutTicks = MSEC_TO_TICK(timeout); } if (xSemaphoreTake(*pSem, timeoutTicks)==pdFALSE) { return kStatus_OSA_Timeout; /* timeout */ } else { return kStatus_OSA_Success; /* semaphore taken */ } }
/* * mac_soft_ring_create * * Create a soft ring, do the necessary setup and bind the worker * thread to the assigned CPU. */ mac_soft_ring_t * mac_soft_ring_create(int id, clock_t wait, void *flent, uint16_t type, pri_t pri, mac_client_impl_t *mcip, mac_soft_ring_set_t *mac_srs, processorid_t cpuid, mac_direct_rx_t rx_func, void *x_arg1, mac_resource_handle_t x_arg2) { mac_soft_ring_t *ringp; char name[S_RING_NAMELEN]; bzero(name, 64); ringp = kmem_cache_alloc(mac_soft_ring_cache, KM_SLEEP); if (type & ST_RING_TCP) { (void) snprintf(name, sizeof (name), "mac_tcp_soft_ring_%d_%p", id, (void *)mac_srs); } else if (type & ST_RING_UDP) { (void) snprintf(name, sizeof (name), "mac_udp_soft_ring_%d_%p", id, (void *)mac_srs); } else { (void) snprintf(name, sizeof (name), "mac_oth_soft_ring_%d_%p", id, (void *)mac_srs); } bzero(ringp, sizeof (mac_soft_ring_t)); (void) strncpy(ringp->s_ring_name, name, S_RING_NAMELEN + 1); ringp->s_ring_name[S_RING_NAMELEN] = '\0'; mutex_init(&ringp->s_ring_lock, NULL, MUTEX_DEFAULT, NULL); ringp->s_ring_notify_cb_info.mcbi_lockp = &ringp->s_ring_lock; ringp->s_ring_type = type; ringp->s_ring_wait = MSEC_TO_TICK(wait); ringp->s_ring_mcip = mcip; ringp->s_ring_set = mac_srs; ringp->s_ring_flent = flent; /* * Protect against access from DR callbacks (mac_walk_srs_bind/unbind) * which can't grab the mac perimeter */ mutex_enter(&mac_srs->srs_lock); ADD_SOFTRING_TO_SET(mac_srs, ringp); mutex_exit(&mac_srs->srs_lock); /* * set the bind CPU to -1 to indicate * no thread affinity set */ ringp->s_ring_cpuid = ringp->s_ring_cpuid_save = -1; ringp->s_ring_worker = thread_create(NULL, 0, mac_soft_ring_worker, ringp, 0, &p0, TS_RUN, pri); if (type & ST_RING_TX) { ringp->s_ring_drain_func = mac_tx_soft_ring_drain; ringp->s_ring_tx_arg1 = x_arg1; ringp->s_ring_tx_arg2 = x_arg2; ringp->s_ring_tx_max_q_cnt = mac_tx_soft_ring_max_q_cnt; ringp->s_ring_tx_hiwat = (mac_tx_soft_ring_hiwat > mac_tx_soft_ring_max_q_cnt) ? mac_tx_soft_ring_max_q_cnt : mac_tx_soft_ring_hiwat; } else { ringp->s_ring_drain_func = mac_rx_soft_ring_drain; ringp->s_ring_rx_func = rx_func; ringp->s_ring_rx_arg1 = x_arg1; ringp->s_ring_rx_arg2 = x_arg2; if (mac_srs->srs_state & SRS_SOFTRING_QUEUE) ringp->s_ring_type |= ST_RING_WORKER_ONLY; } if (cpuid != -1) (void) mac_soft_ring_bind(ringp, cpuid); return (ringp); }
/* * Add a connection to the list of detached TIME_WAIT connections * and set its time to expire. */ void tcp_time_wait_append(tcp_t *tcp) { tcp_stack_t *tcps = tcp->tcp_tcps; squeue_t *sqp = tcp->tcp_connp->conn_sqp; tcp_squeue_priv_t *tcp_time_wait = *((tcp_squeue_priv_t **)squeue_getprivate(sqp, SQPRIVATE_TCP)); tcp_timers_stop(tcp); /* Freed above */ ASSERT(tcp->tcp_timer_tid == 0); ASSERT(tcp->tcp_ack_tid == 0); /* must have happened at the time of detaching the tcp */ ASSERT(tcp->tcp_ptpahn == NULL); ASSERT(tcp->tcp_flow_stopped == 0); ASSERT(tcp->tcp_time_wait_next == NULL); ASSERT(tcp->tcp_time_wait_prev == NULL); ASSERT(tcp->tcp_time_wait_expire == 0); ASSERT(tcp->tcp_listener == NULL); tcp->tcp_time_wait_expire = ddi_get_lbolt64(); /* * Since tcp_time_wait_expire is lbolt64, it should not wrap around * in practice. Hence it cannot be 0. Note that zero means that the * tcp_t is not in the TIME_WAIT list. */ tcp->tcp_time_wait_expire += MSEC_TO_TICK( tcps->tcps_time_wait_interval); ASSERT(TCP_IS_DETACHED(tcp)); ASSERT(tcp->tcp_state == TCPS_TIME_WAIT); ASSERT(tcp->tcp_time_wait_next == NULL); ASSERT(tcp->tcp_time_wait_prev == NULL); TCP_DBGSTAT(tcps, tcp_time_wait); mutex_enter(&tcp_time_wait->tcp_time_wait_lock); if (tcp_time_wait->tcp_time_wait_head == NULL) { ASSERT(tcp_time_wait->tcp_time_wait_tail == NULL); tcp_time_wait->tcp_time_wait_head = tcp; /* * Even if the list was empty before, there may be a timer * running since a tcp_t can be removed from the list * in other places, such as tcp_clean_death(). So check if * a timer is needed. */ if (tcp_time_wait->tcp_time_wait_tid == 0) { tcp_time_wait->tcp_time_wait_tid = timeout_generic(CALLOUT_NORMAL, tcp_time_wait_collector, sqp, (hrtime_t)(tcps->tcps_time_wait_interval + 1) * MICROSEC, CALLOUT_TCP_RESOLUTION, CALLOUT_FLAG_ROUNDUP); } } else { /* * The list is not empty, so a timer must be running. If not, * tcp_time_wait_collector() must be running on this * tcp_time_wait list at the same time. */ ASSERT(tcp_time_wait->tcp_time_wait_tid != 0 || tcp_time_wait->tcp_time_wait_running); ASSERT(tcp_time_wait->tcp_time_wait_tail != NULL); ASSERT(tcp_time_wait->tcp_time_wait_tail->tcp_state == TCPS_TIME_WAIT); tcp_time_wait->tcp_time_wait_tail->tcp_time_wait_next = tcp; tcp->tcp_time_wait_prev = tcp_time_wait->tcp_time_wait_tail; } tcp_time_wait->tcp_time_wait_tail = tcp; mutex_exit(&tcp_time_wait->tcp_time_wait_lock); }
smb_sdrc_t smb_com_echo(struct smb_request *sr) { unsigned short necho; unsigned short nbytes; unsigned short i; struct mbuf_chain reply; char *data; uint16_t pid_hi, pid_lo; pid_hi = sr->smb_pid >> 16; pid_lo = (uint16_t)sr->smb_pid; if (smbsr_decode_vwv(sr, "w", &necho) != 0) return (SDRC_ERROR); /* * Don't let the client fool us into doing * more work than is "reasonable". */ if (necho > smb_max_echo) necho = smb_max_echo; nbytes = sr->smb_bcc; data = smb_srm_zalloc(sr, nbytes); if (smb_mbc_decodef(&sr->smb_data, "#c", nbytes, data)) return (SDRC_ERROR); for (i = 1; i <= necho; ++i) { /* * According to [MS-CIFS] 3.3.5.32 echo is * subject to cancellation. */ if (sr->sr_state != SMB_REQ_STATE_ACTIVE) break; MBC_INIT(&reply, SMB_HEADER_ED_LEN + 10 + nbytes); (void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT, sr->first_smb_com, sr->smb_rcls, sr->smb_reh, sr->smb_err, sr->smb_flg | SMB_FLAGS_REPLY, sr->smb_flg2, pid_hi, sr->smb_sig, sr->smb_tid, pid_lo, sr->smb_uid, sr->smb_mid); (void) smb_mbc_encodef(&reply, "bww#c", 1, i, nbytes, nbytes, data); if (sr->session->signing.flags & SMB_SIGNING_ENABLED) smb_sign_reply(sr, &reply); (void) smb_session_send(sr->session, 0, &reply); delay(MSEC_TO_TICK(100)); } return (SDRC_NO_REPLY); }
/* ARGSUSED */ void sctp_conn_reclaim(void *arg) { netstack_handle_t nh; netstack_t *ns; sctp_stack_t *sctps; extern pgcnt_t lotsfree, needfree; if (!sctp_do_reclaim) return; /* * The reclaim function may be called even when the system is not * really under memory pressure. */ if (freemem >= lotsfree + needfree) return; netstack_next_init(&nh); while ((ns = netstack_next(&nh)) != NULL) { int i; int64_t tot_assoc = 0; /* * During boot time, the first netstack_t is created and * initialized before SCTP has registered with the netstack * framework. If this reclaim function is called before SCTP * has finished its initialization, netstack_next() will * return the first netstack_t (since its netstack_flags is * not NSF_UNINIT). And its netstack_sctp will be NULL. We * need to catch it. * * All subsequent netstack_t creation will not have this * problem since the initialization is not finished until SCTP * has finished its own sctp_stack_t initialization. Hence * netstack_next() will not return one with NULL netstack_sctp. */ if ((sctps = ns->netstack_sctp) == NULL) { netstack_rele(ns); continue; } /* * Even if the system is under memory pressure, the reason may * not be because of SCTP activity. Check the number of * associations in each stack. If the number exceeds the * threshold (maxusers), turn on defensive mode. */ for (i = 0; i < sctps->sctps_sc_cnt; i++) tot_assoc += sctps->sctps_sc[i]->sctp_sc_assoc_cnt; if (tot_assoc < maxusers) { netstack_rele(ns); continue; } mutex_enter(&sctps->sctps_reclaim_lock); if (!sctps->sctps_reclaim) { sctps->sctps_reclaim = B_TRUE; sctps->sctps_reclaim_tid = timeout(sctp_reclaim_timer, sctps, MSEC_TO_TICK(sctps->sctps_reclaim_period)); SCTP_KSTAT(sctps, sctp_reclaim_cnt); } mutex_exit(&sctps->sctps_reclaim_lock); netstack_rele(ns); } netstack_next_fini(&nh); }
/* * Call this function to get information about a peer addr fp. * * Uses ip_attr_connect to avoid explicit use of ire and source address * selection. */ void sctp_get_dest(sctp_t *sctp, sctp_faddr_t *fp) { in6_addr_t laddr; in6_addr_t nexthop; sctp_saddr_ipif_t *sp; int hdrlen; sctp_stack_t *sctps = sctp->sctp_sctps; conn_t *connp = sctp->sctp_connp; iulp_t uinfo; uint_t pmtu; int error; uint32_t flags = IPDF_VERIFY_DST | IPDF_IPSEC | IPDF_SELECT_SRC | IPDF_UNIQUE_DCE; /* * Tell sctp_make_mp it needs to call us again should we not * complete and set the saddr. */ fp->saddr = ipv6_all_zeros; /* * If this addr is not reachable, mark it as unconfirmed for now, the * state will be changed back to unreachable later in this function * if it is still the case. */ if (fp->state == SCTP_FADDRS_UNREACH) { fp->state = SCTP_FADDRS_UNCONFIRMED; } /* * Socket is connected - enable PMTU discovery. */ if (!sctps->sctps_ignore_path_mtu) fp->ixa->ixa_flags |= IXAF_PMTU_DISCOVERY; ip_attr_nexthop(&connp->conn_xmit_ipp, fp->ixa, &fp->faddr, &nexthop); laddr = fp->saddr; error = ip_attr_connect(connp, fp->ixa, &laddr, &fp->faddr, &nexthop, connp->conn_fport, &laddr, &uinfo, flags); if (error != 0) { dprint(3, ("sctp_get_dest: no ire for %x:%x:%x:%x\n", SCTP_PRINTADDR(fp->faddr))); /* * It is tempting to just leave the src addr * unspecified and let IP figure it out, but we * *cannot* do this, since IP may choose a src addr * that is not part of this association... unless * this sctp has bound to all addrs. So if the dest * lookup fails, try to find one in our src addr * list, unless the sctp has bound to all addrs, in * which case we change the src addr to unspec. * * Note that if this is a v6 endpoint but it does * not have any v4 address at this point (e.g. may * have been deleted), sctp_get_valid_addr() will * return mapped INADDR_ANY. In this case, this * address should be marked not reachable so that * it won't be used to send data. */ sctp_set_saddr(sctp, fp); if (fp->state == SCTP_FADDRS_UNREACH) return; goto check_current; } ASSERT(fp->ixa->ixa_ire != NULL); ASSERT(!(fp->ixa->ixa_ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE))); if (!sctp->sctp_loopback) sctp->sctp_loopback = uinfo.iulp_loopback; /* Make sure the laddr is part of this association */ if ((sp = sctp_saddr_lookup(sctp, &laddr, 0)) != NULL && !sp->saddr_ipif_dontsrc) { if (sp->saddr_ipif_unconfirmed == 1) sp->saddr_ipif_unconfirmed = 0; /* We did IPsec policy lookup for laddr already */ fp->saddr = laddr; } else { dprint(2, ("sctp_get_dest: src addr is not part of assoc " "%x:%x:%x:%x\n", SCTP_PRINTADDR(laddr))); /* * Set the src to the first saddr and hope for the best. * Note that this case should very seldomly * happen. One scenario this can happen is an app * explicitly bind() to an address. But that address is * not the preferred source address to send to the peer. */ sctp_set_saddr(sctp, fp); if (fp->state == SCTP_FADDRS_UNREACH) { return; } } /* * Pull out RTO information for this faddr and use it if we don't * have any yet. */ if (fp->srtt == -1 && uinfo.iulp_rtt != 0) { /* The cached value is in ms. */ fp->srtt = MSEC_TO_TICK(uinfo.iulp_rtt); fp->rttvar = MSEC_TO_TICK(uinfo.iulp_rtt_sd); fp->rto = 3 * fp->srtt; /* Bound the RTO by configured min and max values */ if (fp->rto < sctp->sctp_rto_min) { fp->rto = sctp->sctp_rto_min; } if (fp->rto > sctp->sctp_rto_max) { fp->rto = sctp->sctp_rto_max; } SCTP_MAX_RTO(sctp, fp); } pmtu = uinfo.iulp_mtu; /* * Record the MTU for this faddr. If the MTU for this faddr has * changed, check if the assc MTU will also change. */ if (fp->isv4) { hdrlen = sctp->sctp_hdr_len; } else { hdrlen = sctp->sctp_hdr6_len; } if ((fp->sfa_pmss + hdrlen) != pmtu) { /* Make sure that sfa_pmss is a multiple of SCTP_ALIGN. */ fp->sfa_pmss = (pmtu - hdrlen) & ~(SCTP_ALIGN - 1); if (fp->cwnd < (fp->sfa_pmss * 2)) { SET_CWND(fp, fp->sfa_pmss, sctps->sctps_slow_start_initial); } } check_current: if (fp == sctp->sctp_current) sctp_set_faddr_current(sctp, fp); }
/*FUNCTION********************************************************************** * * Function Name : OSA_TimeDelay * Description : This function is used to delay for a number of milliseconds. * *END**************************************************************************/ void OSA_TimeDelay(uint32_t delay) { vTaskDelay(MSEC_TO_TICK(delay)); }
/* * smb_rename_lookup_src * * Lookup the src node, checking for sharing violations and * breaking any existing BATCH oplock. * Populate sr->arg.dirop.fqi * * Upon success, the dnode and fnode will have holds and the * fnode will be in a critical section. These should be * released using smb_rename_release_src(). * * Returns errno values. */ static int smb_rename_lookup_src(smb_request_t *sr) { smb_node_t *src_node, *tnode; DWORD status; int rc; int count; char *path; smb_fqi_t *src_fqi = &sr->arg.dirop.fqi; if (smb_is_stream_name(src_fqi->fq_path.pn_path)) return (EINVAL); /* Lookup the source node */ tnode = sr->tid_tree->t_snode; path = src_fqi->fq_path.pn_path; rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode, &src_fqi->fq_dnode, src_fqi->fq_last_comp); if (rc != 0) return (rc); rc = smb_fsop_lookup(sr, sr->user_cr, 0, tnode, src_fqi->fq_dnode, src_fqi->fq_last_comp, &src_fqi->fq_fnode); if (rc != 0) { smb_node_release(src_fqi->fq_dnode); return (rc); } src_node = src_fqi->fq_fnode; rc = smb_rename_check_attr(sr, src_node, src_fqi->fq_sattr); if (rc != 0) { smb_node_release(src_fqi->fq_fnode); smb_node_release(src_fqi->fq_dnode); return (rc); } /* * Break BATCH oplock before ofile checks. If a client * has a file open, this will force a flush or close, * which may affect the outcome of any share checking. */ (void) smb_oplock_break(sr, src_node, SMB_OPLOCK_BREAK_TO_LEVEL_II | SMB_OPLOCK_BREAK_BATCH); /* * Wait (a little) for the oplock break to be * responded to by clients closing handles. * Hold node->n_lock as reader to keep new * ofiles from showing up after we check. */ smb_node_rdlock(src_node); for (count = 0; count <= 12; count++) { status = smb_node_rename_check(src_node); if (status != NT_STATUS_SHARING_VIOLATION) break; smb_node_unlock(src_node); delay(MSEC_TO_TICK(100)); smb_node_rdlock(src_node); } if (status != NT_STATUS_SUCCESS) { smb_node_unlock(src_node); smb_node_release(src_fqi->fq_fnode); smb_node_release(src_fqi->fq_dnode); return (EPIPE); /* = ERRbadshare */ } /* * Note, the combination of these two: * smb_node_rdlock(node); * nbl_start_crit(node->vp, RW_READER); * is equivalent to this call: * smb_node_start_crit(node, RW_READER) * * Cleanup after this point should use: * smb_node_end_crit(src_node) */ nbl_start_crit(src_node->vp, RW_READER); /* * This checks nbl_share_conflict, nbl_lock_conflict */ status = smb_nbl_conflict(src_node, 0, UINT64_MAX, NBL_RENAME); if (status != NT_STATUS_SUCCESS) { smb_node_end_crit(src_node); smb_node_release(src_fqi->fq_fnode); smb_node_release(src_fqi->fq_dnode); if (status == NT_STATUS_SHARING_VIOLATION) return (EPIPE); /* = ERRbadshare */ return (EACCES); } /* NB: Caller expects holds on src_fqi fnode, dnode */ return (0); }
/* * Same as cv_wait(), but wakes up (after wakeup_time milliseconds) to check * for requests to stop, like cv_wait_sig() but without dealing with signals. * This is a horrible kludge. It is evil. It is vile. It is swill. * If your code has to call this function then your code is the same. */ void cv_wait_stop(kcondvar_t *cvp, kmutex_t *mp, int wakeup_time) { kthread_t *t = curthread; klwp_t *lwp = ttolwp(t); proc_t *p = ttoproc(t); timeout_id_t id; clock_t tim; if (panicstr) return; /* * If there is no lwp, then we don't need to eventually stop it * The check for t_intr is to catch an interrupt thread * that has not yet unpinned the thread underneath. */ if (lwp == NULL || t->t_intr) { cv_wait(cvp, mp); return; } /* * Wakeup in wakeup_time milliseconds, i.e., human time. */ tim = lbolt + MSEC_TO_TICK(wakeup_time); id = realtime_timeout((void (*)(void *))setrun, t, tim - lbolt); thread_lock(t); /* lock the thread */ cv_block((condvar_impl_t *)cvp); thread_unlock_nopreempt(t); mutex_exit(mp); /* ASSERT(no locks are held); */ if ((tim - lbolt) <= 0) /* allow for wrap */ setrun(t); swtch(); (void) untimeout(id); /* * Check for reasons to stop, if lwp_nostop is not true. * See issig_forreal() for explanations of the various stops. */ mutex_enter(&p->p_lock); while (lwp->lwp_nostop == 0 && !(p->p_flag & SEXITLWPS)) { /* * Hold the lwp here for watchpoint manipulation. */ if (t->t_proc_flag & TP_PAUSE) { stop(PR_SUSPENDED, SUSPEND_PAUSE); continue; } /* * System checkpoint. */ if (t->t_proc_flag & TP_CHKPT) { stop(PR_CHECKPOINT, 0); continue; } /* * Honor fork1(), watchpoint activity (remapping a page), * and lwp_suspend() requests. */ if ((p->p_flag & (SHOLDFORK1|SHOLDWATCH)) || (t->t_proc_flag & TP_HOLDLWP)) { stop(PR_SUSPENDED, SUSPEND_NORMAL); continue; } /* * Honor /proc requested stop. */ if (t->t_proc_flag & TP_PRSTOP) { stop(PR_REQUESTED, 0); } /* * If some lwp in the process has already stopped * showing PR_JOBCONTROL, stop in sympathy with it. */ if (p->p_stopsig && t != p->p_agenttp) { stop(PR_JOBCONTROL, p->p_stopsig); continue; } break; } mutex_exit(&p->p_lock); mutex_enter(mp); }
//------------------------------------------------------------------------------ // // Function: OALTimerInit // // General purpose timer 1 is used for system tick. It supports // count/compare mode on 32kHz clock // BOOL OALTimerInit( UINT32 sysTickMSec, UINT32 countsPerMSec, UINT32 countsMargin ) { BOOL rc = FALSE; UINT srcClock; UINT32 sysIntr; UNREFERENCED_PARAMETER(sysTickMSec); UNREFERENCED_PARAMETER(countsPerMSec); UNREFERENCED_PARAMETER(countsMargin); OALMSG(1&&OAL_FUNC, (L"+OALTimerInit(%d, %d, %d)\r\n", sysTickMSec, countsPerMSec, countsMargin )); // Initialize timer state information g_oalTimerContext.maxPeriodMSec = dwOEMMaxIdlePeriod; // Maximum period the timer will interrupt on, in mSec g_oalTimerContext.margin = DELTA_TIME; // Time needed to reprogram the timer interrupt g_oalTimerContext.curCounts = 0; g_oalTimerContext.base = 0; g_oalTimerContext.match = 0xFFFFFFFF; g_oalTimerContext.Posted = 0; // Set idle conversion constant and counters idleconv = MSEC_TO_TICK(1); curridlehigh = 0; curridlelow = 0; // Use variable system tick pOEMUpdateRescheduleTime = OALTimerUpdateRescheduleTime; // Get virtual addresses for hardware g_TimerDevice = BSPGetSysTimerDevice(); // OMAP_DEVICE_GPTIMER1 g_pTimerRegs = OALPAtoUA(GetAddressByDevice(g_TimerDevice)); OALMSG(1 && OAL_FUNC, (L" TimerPA: 0x%x\r\n", GetAddressByDevice(g_TimerDevice))); OALMSG(1 && OAL_FUNC, (L" TimerUA: 0x%x\r\n", g_pTimerRegs)); // Select 32K frequency source clock srcClock = BSPGetSysTimer32KClock(); // k32K_FCLK //PrcmDeviceSetSourceClocks(g_TimerDevice,1,&srcClock); // enable gptimer EnableDeviceClocks(g_TimerDevice, TRUE); // stop timer OALTimerSetReg(&g_pTimerRegs->TCLR, 0); // Soft reset GPTIMER OALTimerSetReg(&g_pTimerRegs->TIOCP, SYSCONFIG_SOFTRESET); // While until done while ((OALTimerGetReg(&g_pTimerRegs->TISTAT) & GPTIMER_TISTAT_RESETDONE) == 0); // Set smart idle OALTimerSetReg( &g_pTimerRegs->TIOCP, SYSCONFIG_SMARTIDLE|SYSCONFIG_ENAWAKEUP| SYSCONFIG_AUTOIDLE ); // Enable posted mode OALTimerSetReg(&g_pTimerRegs->TSICR, GPTIMER_TSICR_POSTED); g_oalTimerContext.Posted = 1; // Set match register to avoid unwanted interrupt OALTimerSetReg(&g_pTimerRegs->TMAR, 0xFFFFFFFF); // Enable match interrupt OALTimerSetReg(&g_pTimerRegs->TIER, GPTIMER_TIER_MATCH); // Enable match wakeup OALTimerSetReg(&g_pTimerRegs->TWER, GPTIMER_TWER_MATCH); // Enable timer in auto-reload and compare mode OALTimerSetReg(&g_pTimerRegs->TCLR, GPTIMER_TCLR_CE|GPTIMER_TCLR_AR|GPTIMER_TCLR_ST); // Wait until write is done //while ((INREG32(&g_pTimerRegs->TWPS) & GPTIMER_TWPS_TCLR) != 0); // Set global variable to tell interrupt module about timer used g_oalTimerIrq = GetIrqByDevice(g_TimerDevice,NULL); // 37 // Request SYSINTR for timer IRQ, it is done to reserve it... sysIntr = OALIntrRequestSysIntr(1, &g_oalTimerIrq, OAL_INTR_FORCE_STATIC); // 17 // Enable System Tick interrupt if (!OEMInterruptEnable(sysIntr, NULL, 0)) { OALMSG(OAL_ERROR, ( L"ERROR: OALTimerInit: Interrupt enable for system timer failed" )); goto cleanUp; } // Initialize timer to maximum period UpdatePeriod(g_oalTimerContext.maxPeriodMSec); // Done rc = TRUE; cleanUp: OALMSG(1 && OAL_FUNC, (L"-OALTimerInit(rc = %d)\r\n", rc)); return rc; }
/* * smb_common_rename * * Common code for renaming a file. * * If the source and destination are identical, we go through all * the checks but we don't actually do the rename. If the source * and destination files differ only in case, we do a case-sensitive * rename. Otherwise, we do a full case-insensitive rename. * * Returns NT status values. * * Similar to smb_make_link(), below. */ uint32_t smb_common_rename(smb_request_t *sr, smb_fqi_t *src_fqi, smb_fqi_t *dst_fqi) { smb_node_t *src_fnode, *src_dnode, *dst_dnode; smb_node_t *dst_fnode = 0; smb_node_t *tnode; char *new_name, *path; DWORD status; int rc, count; tnode = sr->tid_tree->t_snode; path = dst_fqi->fq_path.pn_path; /* Check if attempting to rename a stream - not yet supported */ rc = smb_rename_check_stream(src_fqi, dst_fqi); if (rc != 0) return (smb_rename_errno2status(rc)); /* * The source node may already have been provided, * i.e. when called by SMB1/SMB2 smb_setinfo_rename. * Not provided by smb_com_rename, smb_com_nt_rename. */ if (src_fqi->fq_fnode) { smb_node_start_crit(src_fqi->fq_fnode, RW_READER); smb_node_ref(src_fqi->fq_fnode); smb_node_ref(src_fqi->fq_dnode); } else { /* lookup and validate src node */ rc = smb_rename_lookup_src(sr); if (rc != 0) return (smb_rename_errno2status(rc)); } src_fnode = src_fqi->fq_fnode; src_dnode = src_fqi->fq_dnode; /* * Find the destination dnode and last component. * May already be provided, i.e. when called via * SMB1 trans2 setinfo. */ if (dst_fqi->fq_dnode) { /* called via smb_set_rename_info */ smb_node_ref(dst_fqi->fq_dnode); } else { /* called via smb2_setf_rename, smb_com_rename, etc. */ rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode, &dst_fqi->fq_dnode, dst_fqi->fq_last_comp); if (rc != 0) { smb_rename_release_src(sr); return (smb_rename_errno2status(rc)); } } dst_dnode = dst_fqi->fq_dnode; new_name = dst_fqi->fq_last_comp; /* If exact name match in same directory, we're done */ if ((src_dnode == dst_dnode) && (strcmp(src_fnode->od_name, new_name) == 0)) { smb_rename_release_src(sr); smb_node_release(dst_dnode); return (0); } /* Lookup destination node */ rc = smb_fsop_lookup(sr, sr->user_cr, 0, tnode, dst_dnode, new_name, &dst_fqi->fq_fnode); /* If the destination node doesn't already exist, validate new_name. */ if (rc == ENOENT) { if (smb_is_invalid_filename(new_name)) { smb_rename_release_src(sr); smb_node_release(dst_dnode); return (NT_STATUS_OBJECT_NAME_INVALID); } } /* * Handle case where changing case of the same directory entry. * * If we found the dst node in the same directory as the src node, * and their names differ only in case: * * If the tree is case sensitive (or mixed): * Do case sensitive lookup to see if exact match exists. * If the exact match is the same node as src_node we're done. * * If the tree is case insensitive: * There is currently no way to tell if the case is different * or not, so do the rename (unless the specified new name was * mangled). */ if ((rc == 0) && (src_dnode == dst_dnode) && (smb_strcasecmp(src_fnode->od_name, dst_fqi->fq_fnode->od_name, 0) == 0)) { smb_node_release(dst_fqi->fq_fnode); dst_fqi->fq_fnode = NULL; if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_NO_CASESENSITIVE)) { if (smb_strcasecmp(src_fnode->od_name, dst_fqi->fq_last_comp, 0) != 0) { smb_rename_release_src(sr); smb_node_release(dst_dnode); return (0); } } else { rc = smb_fsop_lookup(sr, sr->user_cr, SMB_CASE_SENSITIVE, tnode, dst_dnode, new_name, &dst_fqi->fq_fnode); if ((rc == 0) && (dst_fqi->fq_fnode == src_fnode)) { smb_rename_release_src(sr); smb_node_release(dst_fqi->fq_fnode); smb_node_release(dst_dnode); return (0); } } } if ((rc != 0) && (rc != ENOENT)) { smb_rename_release_src(sr); smb_node_release(dst_fqi->fq_dnode); return (smb_rename_errno2status(rc)); } if (dst_fqi->fq_fnode) { /* * Destination already exists. Do delete checks. */ dst_fnode = dst_fqi->fq_fnode; if (!(sr->arg.dirop.flags && SMB_RENAME_FLAG_OVERWRITE)) { smb_rename_release_src(sr); smb_node_release(dst_fnode); smb_node_release(dst_dnode); return (NT_STATUS_OBJECT_NAME_COLLISION); } (void) smb_oplock_break(sr, dst_fnode, SMB_OPLOCK_BREAK_TO_NONE | SMB_OPLOCK_BREAK_BATCH); /* * Wait (a little) for the oplock break to be * responded to by clients closing handles. * Hold node->n_lock as reader to keep new * ofiles from showing up after we check. */ smb_node_rdlock(dst_fnode); for (count = 0; count <= 12; count++) { status = smb_node_delete_check(dst_fnode); if (status != NT_STATUS_SHARING_VIOLATION) break; smb_node_unlock(dst_fnode); delay(MSEC_TO_TICK(100)); smb_node_rdlock(dst_fnode); } if (status != NT_STATUS_SUCCESS) { smb_node_unlock(dst_fnode); smb_rename_release_src(sr); smb_node_release(dst_fnode); smb_node_release(dst_dnode); return (NT_STATUS_ACCESS_DENIED); } /* * Note, the combination of these two: * smb_node_rdlock(node); * nbl_start_crit(node->vp, RW_READER); * is equivalent to this call: * smb_node_start_crit(node, RW_READER) * * Cleanup after this point should use: * smb_node_end_crit(dst_fnode) */ nbl_start_crit(dst_fnode->vp, RW_READER); /* * This checks nbl_share_conflict, nbl_lock_conflict */ status = smb_nbl_conflict(dst_fnode, 0, UINT64_MAX, NBL_REMOVE); if (status != NT_STATUS_SUCCESS) { smb_node_end_crit(dst_fnode); smb_rename_release_src(sr); smb_node_release(dst_fnode); smb_node_release(dst_dnode); return (NT_STATUS_ACCESS_DENIED); } new_name = dst_fnode->od_name; } rc = smb_fsop_rename(sr, sr->user_cr, src_dnode, src_fnode->od_name, dst_dnode, new_name); if (rc == 0) { /* * Note that renames in the same directory are normally * delivered in {old,new} pairs, and clients expect them * in that order, if both events are delivered. */ int a_src, a_dst; /* action codes */ if (src_dnode == dst_dnode) { a_src = FILE_ACTION_RENAMED_OLD_NAME; a_dst = FILE_ACTION_RENAMED_NEW_NAME; } else { a_src = FILE_ACTION_REMOVED; a_dst = FILE_ACTION_ADDED; } smb_node_notify_change(src_dnode, a_src, src_fnode->od_name); smb_node_notify_change(dst_dnode, a_dst, new_name); } smb_rename_release_src(sr); if (dst_fqi->fq_fnode) { smb_node_end_crit(dst_fnode); smb_node_release(dst_fnode); } smb_node_release(dst_dnode); return (smb_rename_errno2status(rc)); }