Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1299 lines
23 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. atqbmon.cxx
  5. Abstract:
  6. ATQ Backlog Monitor
  7. Author:
  8. 01-Dec-1998 MCourage
  9. Revision History:
  10. --*/
  11. #include "isatq.hxx"
  12. #include "atqbmon.hxx"
  13. ATQ_BACKLOG_MONITOR * g_pAtqBacklogMonitor = NULL;
  14. ATQ_BACKLOG_MONITOR::ATQ_BACKLOG_MONITOR(
  15. VOID
  16. )
  17. /*++
  18. Routine Description:
  19. Constructor sets up the list and the lock.
  20. Arguments:
  21. None
  22. --*/
  23. {
  24. INITIALIZE_CRITICAL_SECTION( &m_csLock );
  25. InitializeListHead( &m_ListHead );
  26. }
  27. ATQ_BACKLOG_MONITOR::~ATQ_BACKLOG_MONITOR(
  28. VOID
  29. )
  30. /*++
  31. Routine Description:
  32. Destructor cleans up the list and the lock.
  33. Arguments:
  34. None
  35. --*/
  36. {
  37. LIST_ENTRY * pEntry;
  38. ATQ_BMON_SET * pBmonSet;
  39. //
  40. // traverse the list and remove all sets
  41. //
  42. while (!IsListEmpty( &m_ListHead )) {
  43. pEntry = RemoveHeadList( &m_ListHead );
  44. pBmonSet = CONTAINING_RECORD( pEntry, ATQ_BMON_SET, m_SetList );
  45. DBG_ASSERT( pBmonSet->IsEmpty() );
  46. DBG_REQUIRE( pBmonSet->Cleanup() );
  47. }
  48. DeleteCriticalSection( &m_csLock );
  49. }
  50. BOOL
  51. ATQ_BACKLOG_MONITOR::AddEntry(
  52. ATQ_BMON_ENTRY * pBmonEntry
  53. )
  54. /*++
  55. Routine Description:
  56. Adds an entry to the next available ATQ_BMON_SET.
  57. Makes a new set if all current sets are full.
  58. Arguments:
  59. pBmonEntry - The entry to be added
  60. Return Values:
  61. TRUE on success
  62. --*/
  63. {
  64. LIST_ENTRY * pCurrent;
  65. ATQ_BMON_SET * pBmonSet;
  66. BOOL bRetval;
  67. if (!pBmonEntry) {
  68. return TRUE;
  69. }
  70. bRetval = FALSE;
  71. Lock();
  72. for (pCurrent = m_ListHead.Flink;
  73. pCurrent != &m_ListHead;
  74. pCurrent = pCurrent->Flink) {
  75. pBmonSet = CONTAINING_RECORD( pCurrent, ATQ_BMON_SET, m_SetList );
  76. if (pBmonSet->IsNotFull() && pBmonSet->AddEntry(pBmonEntry)) {
  77. bRetval = TRUE;
  78. break;
  79. }
  80. }
  81. if (!bRetval) {
  82. //
  83. // Couldn't find a set with space
  84. // so try to make a new one.
  85. //
  86. pBmonSet = new ATQ_BMON_SET;
  87. if (pBmonSet && pBmonSet->Initialize()) {
  88. InsertHeadList( &m_ListHead, &pBmonSet->m_SetList );
  89. bRetval = pBmonSet->AddEntry(pBmonEntry);
  90. }
  91. }
  92. Unlock();
  93. return bRetval;
  94. }
  95. BOOL
  96. ATQ_BACKLOG_MONITOR::RemoveEntry(
  97. ATQ_BMON_ENTRY * pBmonEntry
  98. )
  99. /*++
  100. Routine Description:
  101. Removes an entry from its containing ATQ_BMON_SET.
  102. If the set is empty it is removed from the list
  103. of sets.
  104. Arguments:
  105. pBmonEntry - The entry to be removed
  106. Return Values:
  107. TRUE on success
  108. --*/
  109. {
  110. ATQ_BMON_SET * pBmonSet;
  111. if (!pBmonEntry) {
  112. return TRUE;
  113. }
  114. DBG_ASSERT( pBmonEntry && pBmonEntry->CheckSignature() );
  115. pBmonSet = pBmonEntry->GetContainingBmonSet();
  116. DBG_ASSERT( pBmonSet );
  117. return pBmonSet->RemoveEntry(pBmonEntry);
  118. }
  119. BOOL
  120. ATQ_BACKLOG_MONITOR::PauseEntry(
  121. ATQ_BMON_ENTRY * pBmonEntry
  122. )
  123. /*++
  124. Routine Description:
  125. Pauses an entry in its containing ATQ_BMON_SET.
  126. The entry will remain in the set, but will
  127. not send notifications.
  128. Arguments:
  129. pBmonEntry - The entry to be paused
  130. Return Values:
  131. TRUE on success
  132. --*/
  133. {
  134. ATQ_BMON_SET * pBmonSet;
  135. if (!pBmonEntry) {
  136. return TRUE;
  137. }
  138. DBG_ASSERT( pBmonEntry && pBmonEntry->CheckSignature() );
  139. pBmonSet = pBmonEntry->GetContainingBmonSet();
  140. DBG_ASSERT( pBmonSet );
  141. return pBmonSet->PauseEntry(pBmonEntry);
  142. }
  143. BOOL
  144. ATQ_BACKLOG_MONITOR::ResumeEntry(
  145. ATQ_BMON_ENTRY * pBmonEntry
  146. )
  147. /*++
  148. Routine Description:
  149. Undoes PauseEntry. The entry in question
  150. will get notifications again
  151. Arguments:
  152. pBmonEntry - The entry to be resumed
  153. Return Values:
  154. TRUE on success
  155. --*/
  156. {
  157. ATQ_BMON_SET * pBmonSet;
  158. if (!pBmonEntry) {
  159. return TRUE;
  160. }
  161. DBG_ASSERT( pBmonEntry && pBmonEntry->CheckSignature() );
  162. pBmonSet = pBmonEntry->GetContainingBmonSet();
  163. DBG_ASSERT( pBmonSet );
  164. return pBmonSet->ResumeEntry(pBmonEntry);
  165. }
  166. ATQ_BMON_ENTRY::ATQ_BMON_ENTRY(
  167. SOCKET s
  168. )
  169. /*++
  170. Routine Description:
  171. Constructor sets up signature etc.
  172. Arguments:
  173. None
  174. --*/
  175. {
  176. DBG_ASSERT( s );
  177. m_Signature = ATQ_BMON_ENTRY_SIGNATURE;
  178. m_Socket = s;
  179. m_hAddRemoveEvent = NULL;
  180. m_BmonOpcode = BMON_INVALID;
  181. m_pBmonSet = NULL;
  182. m_dwErr = NO_ERROR;
  183. }
  184. ATQ_BMON_ENTRY::~ATQ_BMON_ENTRY(
  185. VOID
  186. )
  187. /*++
  188. Routine Description:
  189. Destructor sets up signature and closes event.
  190. Arguments:
  191. None
  192. --*/
  193. {
  194. DBG_ASSERT( CheckSignature() );
  195. DBG_ASSERT( m_Socket );
  196. m_Signature = ATQ_FREE_BMON_ENTRY_SIGNATURE;
  197. DBG_REQUIRE( CloseHandle( m_hAddRemoveEvent ) );
  198. }
  199. BOOL
  200. ATQ_BMON_ENTRY::InitEvent(
  201. VOID
  202. )
  203. /*++
  204. Routine Description:
  205. Sets up the AddRemove event that we use
  206. to synchronise adding and removing of entries.
  207. Arguments:
  208. None
  209. Return Values:
  210. TRUE on success
  211. --*/
  212. {
  213. DBG_ASSERT( CheckSignature() );
  214. DBG_ASSERT( m_hAddRemoveEvent == NULL );
  215. m_hAddRemoveEvent = CreateEvent(
  216. NULL, // default security
  217. FALSE, // do auto-reset
  218. FALSE, // init state false
  219. NULL // no name
  220. );
  221. if (m_hAddRemoveEvent == NULL) {
  222. m_dwErr = GetLastError();
  223. }
  224. return (m_hAddRemoveEvent != NULL);
  225. }
  226. VOID
  227. ATQ_BMON_ENTRY::SignalAddRemove(
  228. DWORD dwError
  229. )
  230. /*++
  231. Routine Description:
  232. Signals the AddRemove event. Clients adding or
  233. removing the entry will be blocked on its event.
  234. Arguments:
  235. None
  236. Return Values:
  237. None
  238. --*/
  239. {
  240. DBG_ASSERT( CheckSignature() );
  241. DBG_ASSERT( m_hAddRemoveEvent != NULL );
  242. m_dwErr = dwError;
  243. DBG_REQUIRE( SetEvent(m_hAddRemoveEvent) );
  244. }
  245. BOOL
  246. ATQ_BMON_ENTRY::WaitForAddRemove(
  247. VOID
  248. )
  249. /*++
  250. Routine Description:
  251. Call this function while waiting for
  252. the entry to be added to or removed from a set.
  253. Arguments:
  254. None
  255. Return Values:
  256. TRUE on success
  257. --*/
  258. {
  259. DWORD dwResult;
  260. DBG_ASSERT( CheckSignature() );
  261. DBG_ASSERT( m_hAddRemoveEvent != NULL );
  262. //
  263. // If the monitor thread dies, don't bother waiting for notification from
  264. // it regarding add/removal.
  265. //
  266. Retry:
  267. if ( m_pBmonSet && !m_pBmonSet->ThreadFinished() )
  268. {
  269. dwResult = WaitForSingleObject(m_hAddRemoveEvent, 10000 );
  270. if ( dwResult == WAIT_TIMEOUT )
  271. {
  272. goto Retry;
  273. }
  274. }
  275. else
  276. {
  277. dwResult = WAIT_OBJECT_0;
  278. }
  279. DBG_ASSERT( dwResult == WAIT_OBJECT_0 );
  280. return (dwResult == WAIT_OBJECT_0);
  281. }
  282. BOOL
  283. BMON_WAKEUP_ENTRY::Callback(
  284. VOID
  285. )
  286. /*++
  287. Routine Description:
  288. The sole purpose of the BMON_WAKEUP_ENTRY is to
  289. get the main thread to wake up and call
  290. SynchronizeSets. All we have to do here is
  291. do a read so that we can wake up again in
  292. the future.
  293. Arguments:
  294. None
  295. Return Values:
  296. TRUE if successful, else FALSE
  297. --*/
  298. {
  299. INT err;
  300. DWORD dwBuff;
  301. ATQ_BMON_SET * pBmonSet;
  302. DBG_ASSERT( CheckSignature() );
  303. //
  304. // do a read to clear the wakeup signal
  305. //
  306. err = recvfrom(
  307. GetSocket(), // our socket
  308. (PCHAR) &dwBuff, // read buffer
  309. sizeof(dwBuff), // buffer len
  310. 0, // flags
  311. NULL, // src addr
  312. NULL // src addr len
  313. );
  314. if ( err == SOCKET_ERROR ) {
  315. DBGPRINTF((DBG_CONTEXT,
  316. "Error %d in recvfrom\n", WSAGetLastError()));
  317. return FALSE;
  318. } else {
  319. DBG_ASSERT(dwBuff == ATQ_BMON_WAKEUP_MESSAGE);
  320. return TRUE;
  321. }
  322. }
  323. ATQ_BMON_SET::ATQ_BMON_SET(
  324. VOID
  325. )
  326. /*++
  327. Routine Description:
  328. Constructor sets up critsec and sets.
  329. Arguments:
  330. None
  331. --*/
  332. {
  333. INITIALIZE_CRITICAL_SECTION( &m_csLock );
  334. memset(m_apEntrySet, 0, sizeof(m_apEntrySet));
  335. FD_ZERO( &m_ListenSet );
  336. m_SetSize = 0;
  337. m_pWakeupEntry = NULL;
  338. m_fCleanup = FALSE;
  339. m_fDoSleep = FALSE;
  340. m_fThreadFinished = FALSE;
  341. m_dwError = NO_ERROR;
  342. }
  343. ATQ_BMON_SET::~ATQ_BMON_SET(
  344. VOID
  345. )
  346. /*++
  347. Routine Description:
  348. Destructor cleans up critsec.
  349. Arguments:
  350. None
  351. --*/
  352. {
  353. DBG_ASSERT( m_SetSize == 0 );
  354. //
  355. // get rid of the wakeup entry
  356. //
  357. DBG_REQUIRE( 0 == closesocket(m_pWakeupEntry->GetSocket()) );
  358. delete m_pWakeupEntry;
  359. DeleteCriticalSection(&m_csLock);
  360. }
  361. BOOL
  362. ATQ_BMON_SET::Initialize(
  363. VOID
  364. )
  365. /*++
  366. Routine Description:
  367. Sets up the Wakeup entry and starts
  368. our thread.
  369. Arguments:
  370. None
  371. Return Values:
  372. TRUE on success
  373. --*/
  374. {
  375. BOOL bRetval;
  376. SOCKET s;
  377. SOCKADDR_IN sockAddr;
  378. INT err;
  379. BMON_WAKEUP_ENTRY * pWakeup;
  380. HANDLE hThread;
  381. DWORD dwError = NO_ERROR;
  382. WORD wPort = ATQ_BMON_WAKEUP_PORT;
  383. bRetval = FALSE;
  384. //
  385. // set up wakeup entry
  386. //
  387. s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  388. if (s == INVALID_SOCKET) {
  389. dwError = WSAGetLastError();
  390. goto exit;
  391. }
  392. ZeroMemory(&sockAddr, sizeof(sockAddr));
  393. sockAddr.sin_family = AF_INET;
  394. sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  395. sockAddr.sin_port = htons(wPort);
  396. err = bind(s, (PSOCKADDR)&sockAddr, sizeof(sockAddr));
  397. while ((err == SOCKET_ERROR)
  398. && (WSAGetLastError() == WSAEADDRINUSE)
  399. && (wPort < ATQ_BMON_WAKEUP_PORT_MAX)) {
  400. //
  401. // try another port
  402. //
  403. wPort++;
  404. sockAddr.sin_port = htons(wPort);
  405. err = bind(s, (PSOCKADDR)&sockAddr, sizeof(sockAddr));
  406. }
  407. if ( err == SOCKET_ERROR ) {
  408. DBGERROR((DBG_CONTEXT,"Error %d in bind\n", WSAGetLastError()));
  409. dwError = WSAGetLastError();
  410. closesocket(s);
  411. goto exit;
  412. }
  413. pWakeup = new BMON_WAKEUP_ENTRY(s);
  414. if ( pWakeup == NULL )
  415. {
  416. dwError = ERROR_NOT_ENOUGH_MEMORY;
  417. goto exit;
  418. }
  419. if (!pWakeup->InitEvent()) {
  420. delete pWakeup;
  421. pWakeup = NULL;
  422. goto exit;
  423. }
  424. pWakeup->SetContainingBmonSet(this);
  425. pWakeup->SetOpcode(BMON_WAIT);
  426. m_pWakeupEntry = pWakeup;
  427. m_Port = wPort;
  428. //
  429. // just jam this entry into the lists
  430. //
  431. DBG_ASSERT(m_SetSize == 0);
  432. m_SetSize = 1;
  433. m_apEntrySet[0] = pWakeup;
  434. FD_SET(pWakeup->GetSocket(), &m_ListenSet);
  435. //
  436. // now set up our thread. from now on you
  437. // have to Lock before manipulating the
  438. // lists
  439. //
  440. m_hThread = CreateThread(
  441. NULL, // defualt security
  442. 0, // default stack
  443. ::BmonThreadFunc, // thread func
  444. this, // func parameter
  445. 0, // flags
  446. NULL // discard tid
  447. );
  448. if (m_hThread) {
  449. //
  450. // it worked!
  451. //
  452. bRetval = TRUE;
  453. } else {
  454. //
  455. // doh! clean up the wakeup entry
  456. //
  457. dwError = GetLastError();
  458. closesocket( pWakeup->GetSocket() );
  459. delete pWakeup;
  460. m_SetSize = 0;
  461. }
  462. exit:
  463. if (dwError != NO_ERROR) {
  464. SetLastError(dwError);
  465. }
  466. return bRetval;
  467. }
  468. BOOL
  469. ATQ_BMON_SET::Cleanup(
  470. VOID
  471. )
  472. /*++
  473. Routine Description:
  474. Tells the select thread to clean up by
  475. removing the wakeup entry.
  476. Arguments:
  477. None
  478. Return Values:
  479. TRUE on success
  480. --*/
  481. {
  482. //
  483. // Cleanup is done when wakup entry
  484. // is removed.
  485. //
  486. // Don't use RemoveEntry, because the
  487. // other thread will delete the wakeup
  488. // entry.
  489. //
  490. DBG_ASSERT( m_pWakeupEntry && m_pWakeupEntry->CheckSignature() );
  491. m_pWakeupEntry->SetOpcode(BMON_REMOVE);
  492. Wakeup();
  493. //
  494. // Wait a reasonable amount of time for the thread to go away.
  495. //
  496. WaitForSingleObject( m_hThread, 10000 );
  497. CloseHandle( m_hThread );
  498. m_hThread = NULL;
  499. delete this;
  500. return TRUE;
  501. }
  502. BOOL
  503. ATQ_BMON_SET::IsEmpty(
  504. VOID
  505. )
  506. /*++
  507. Routine Description:
  508. This tells you if there are sockets in the
  509. set. Note that one socket is the wakeup
  510. socket, so a count of one means we're empty.
  511. Arguments:
  512. None
  513. Return Values:
  514. TRUE on empty
  515. --*/
  516. {
  517. BOOL bRetval;
  518. Lock();
  519. bRetval = (m_SetSize <= 1);
  520. DBG_ASSERT( m_SetSize <= FD_SETSIZE );
  521. Unlock();
  522. return bRetval;
  523. }
  524. BOOL
  525. ATQ_BMON_SET::IsNotFull(
  526. VOID
  527. )
  528. /*++
  529. Routine Description:
  530. This tells you if there is room for more sockets
  531. in the set. Note that one socket is the wakeup
  532. socket.
  533. Arguments:
  534. None
  535. Return Values:
  536. TRUE when space is available
  537. --*/
  538. {
  539. BOOL bRetval;
  540. Lock();
  541. bRetval = (m_SetSize < FD_SETSIZE);
  542. DBG_ASSERT( m_SetSize <= FD_SETSIZE );
  543. Unlock();
  544. return bRetval;
  545. }
  546. BOOL
  547. ATQ_BMON_SET::AddEntry(
  548. ATQ_BMON_ENTRY * pBmonEntry
  549. )
  550. /*++
  551. Routine Description:
  552. Add an entry to the set
  553. Arguments:
  554. pBmonEntry - the entry to be added
  555. Return Values:
  556. TRUE on success
  557. --*/
  558. {
  559. DWORD i;
  560. BOOL bAdded = FALSE;
  561. DWORD dwError;
  562. pBmonEntry->SetOpcode(BMON_ADD);
  563. Lock();
  564. for (i = 0; i < FD_SETSIZE; i++) {
  565. if (!m_apEntrySet[i]) {
  566. m_apEntrySet[i] = pBmonEntry;
  567. pBmonEntry->SetContainingBmonSet(this);
  568. bAdded = TRUE;
  569. m_SetSize++;
  570. DBG_ASSERT( m_SetSize <= FD_SETSIZE );
  571. break;
  572. }
  573. }
  574. Unlock();
  575. if (bAdded) {
  576. Wakeup();
  577. pBmonEntry->WaitForAddRemove();
  578. dwError = pBmonEntry->GetError();
  579. if (dwError) {
  580. //
  581. // other thread will remove from list
  582. //
  583. SetLastError(dwError);
  584. bAdded = FALSE;
  585. }
  586. }
  587. return bAdded;
  588. }
  589. BOOL
  590. ATQ_BMON_SET::RemoveEntry(
  591. ATQ_BMON_ENTRY * pBmonEntry
  592. )
  593. /*++
  594. Routine Description:
  595. Remove an entry from the set
  596. Arguments:
  597. pBmonEntry - the entry to be removed
  598. Return Values:
  599. TRUE on success
  600. --*/
  601. {
  602. DWORD i;
  603. BOOL bRemoved = FALSE;
  604. pBmonEntry->SetOpcode(BMON_REMOVE);
  605. Wakeup();
  606. pBmonEntry->WaitForAddRemove();
  607. return (pBmonEntry->GetError() == NO_ERROR);
  608. }
  609. BOOL
  610. ATQ_BMON_SET::PauseEntry(
  611. ATQ_BMON_ENTRY * pBmonEntry
  612. )
  613. /*++
  614. Routine Description:
  615. Pause an entry in the set. The entry's
  616. socket will be removed from the FD_SET,
  617. but the entry will stay.
  618. Arguments:
  619. pBmonEntry - the entry to be paused
  620. Return Values:
  621. TRUE on success
  622. --*/
  623. {
  624. DWORD i;
  625. BOOL bRemoved = FALSE;
  626. DBGPRINTF((DBG_CONTEXT,
  627. "Pausing backlog monitor entry %p\n",
  628. pBmonEntry));
  629. pBmonEntry->SetOpcode(BMON_PAUSE);
  630. Wakeup();
  631. //
  632. // We don't do the event stuff for pause and
  633. // resume. It's a pain because the client will
  634. // want to pause from within the callback
  635. // function.
  636. //
  637. return (TRUE);
  638. }
  639. BOOL
  640. ATQ_BMON_SET::ResumeEntry(
  641. ATQ_BMON_ENTRY * pBmonEntry
  642. )
  643. /*++
  644. Routine Description:
  645. Resume an entry in the set. The entry's
  646. socket will be added back to the FD_SET.
  647. Arguments:
  648. pBmonEntry - the entry to be resumed
  649. Return Values:
  650. TRUE on success
  651. --*/
  652. {
  653. DWORD i;
  654. BOOL bRemoved = FALSE;
  655. if (pBmonEntry->GetOpcode() == BMON_NOWAIT) {
  656. DBGPRINTF((DBG_CONTEXT,
  657. "Resuming backlog monitor entry %p\n",
  658. pBmonEntry));
  659. pBmonEntry->SetOpcode(BMON_RESUME);
  660. Wakeup();
  661. }
  662. //
  663. // We don't do the event stuff for pause and
  664. // resume. It's a pain because the client will
  665. // want to pause from within the callback
  666. // function.
  667. //
  668. return (TRUE);
  669. }
  670. VOID
  671. ATQ_BMON_SET::BmonThreadFunc(
  672. VOID
  673. )
  674. /*++
  675. Routine Description:
  676. This function is for the set's select thread.
  677. It calls accept with the listen set, and calls
  678. notification functions for all sockets that
  679. are ready.
  680. SynchronizeSets returns false when it's time
  681. to shut down.
  682. Arguments:
  683. None
  684. Return Values:
  685. None
  686. --*/
  687. {
  688. INT err;
  689. while (SynchronizeSets()) {
  690. err = select(
  691. 0, // junk
  692. &m_ListenSet, // readfds
  693. NULL, // writefds
  694. NULL, // exceptfds
  695. NULL // want to block
  696. );
  697. if (err != SOCKET_ERROR) {
  698. DBG_ASSERT(err > 0);
  699. if ( !NotifyEntries() )
  700. {
  701. //
  702. // If we couldn't notify the entries, stop doing our thing
  703. //
  704. m_dwError = GetLastError();
  705. m_dwError |= BMON_NOTIFY_ERROR;
  706. break;
  707. }
  708. } else {
  709. //
  710. // Actually let's take the general approach that the moment the
  711. // Backlog monitor sees trouble, it should stop. This avoids
  712. // low memory situations where the backlog monitor just spins,
  713. // thus becoming it's own denial of service attack.
  714. //
  715. m_dwError = WSAGetLastError();
  716. m_dwError |= BMON_SELECT_ERROR;
  717. break;
  718. DBGPRINTF(( DBG_CONTEXT,
  719. "Select failed with error %d\n",
  720. WSAGetLastError()
  721. ));
  722. }
  723. if ( m_fDoSleep )
  724. {
  725. //
  726. // Now sleep for a while. It will take time for unconnected to go away.
  727. // We don't want to spin
  728. //
  729. // Of course, this means we don't do useful work on any other endpoints
  730. // which may also be in trouble. Oh well.
  731. //
  732. Sleep( 5000 );
  733. m_fDoSleep = FALSE;
  734. }
  735. }
  736. m_fThreadFinished = TRUE;
  737. }
  738. VOID
  739. ATQ_BMON_SET::Wakeup(
  740. VOID
  741. )
  742. /*++
  743. Routine Description:
  744. We call this function when adding or removing
  745. an entry. Writing to the wakeup socket wakes
  746. up the select thread.
  747. Arguments:
  748. None
  749. Return Values:
  750. None
  751. --*/
  752. {
  753. SOCKADDR_IN sockAddr;
  754. INT err;
  755. DWORD dwBuf;
  756. sockAddr.sin_family = AF_INET;
  757. sockAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  758. sockAddr.sin_port = htons(m_Port);
  759. dwBuf = ATQ_BMON_WAKEUP_MESSAGE;
  760. err = sendto(
  761. m_pWakeupEntry->GetSocket(),
  762. (PCHAR)&dwBuf,
  763. sizeof(dwBuf),
  764. 0,
  765. (PSOCKADDR)&sockAddr,
  766. sizeof(sockAddr)
  767. );
  768. if ( err == SOCKET_ERROR ) {
  769. m_dwError = WSAGetLastError();
  770. m_dwError |= BMON_SENDTO_ERROR;
  771. DBGPRINTF((DBG_CONTEXT,
  772. "Error %d in sendto\n",WSAGetLastError()));
  773. }
  774. }
  775. BOOL
  776. ATQ_BMON_SET::SynchronizeSets(
  777. VOID
  778. )
  779. /*++
  780. Routine Description:
  781. This function updates our FD_SET to reflect
  782. what's in the entry set, and also notifies
  783. entries which have been added or removed.
  784. We also check to see if it's time to shut
  785. down (as indicated by the removal of the
  786. wakeup entry.
  787. Arguments:
  788. None
  789. Return Values:
  790. TRUE to continue operating
  791. FALSE on shutdown
  792. --*/
  793. {
  794. DWORD i;
  795. ATQ_BMON_ENTRY * pBmonEntry;
  796. BOOL bRetval;
  797. bRetval = TRUE;
  798. Lock();
  799. //
  800. // clear out whatever is there now
  801. //
  802. FD_ZERO(&m_ListenSet);
  803. //
  804. // put in everything we want
  805. //
  806. for (i = 0; i < FD_SETSIZE; i++) {
  807. pBmonEntry = m_apEntrySet[i];
  808. if (pBmonEntry) {
  809. DBG_ASSERT( pBmonEntry->CheckSignature() );
  810. switch(pBmonEntry->GetOpcode()) {
  811. case BMON_ADD:
  812. FD_SET(pBmonEntry->GetSocket(), &m_ListenSet);
  813. pBmonEntry->SetOpcode(BMON_WAIT);
  814. pBmonEntry->SignalAddRemove(NO_ERROR);
  815. break;
  816. case BMON_RESUME:
  817. FD_SET(pBmonEntry->GetSocket(), &m_ListenSet);
  818. pBmonEntry->SetOpcode(BMON_WAIT);
  819. break;
  820. case BMON_PAUSE:
  821. pBmonEntry->SetOpcode(BMON_NOWAIT);
  822. pBmonEntry->SignalAddRemove(NO_ERROR);
  823. break;
  824. case BMON_REMOVE:
  825. if (pBmonEntry == m_pWakeupEntry) {
  826. //
  827. // this means it's time to shut down
  828. //
  829. bRetval = FALSE;
  830. }
  831. m_apEntrySet[i] = NULL;
  832. m_SetSize--;
  833. pBmonEntry->SetContainingBmonSet(NULL);
  834. pBmonEntry->SignalAddRemove(NO_ERROR);
  835. break;
  836. case BMON_WAIT:
  837. FD_SET(pBmonEntry->GetSocket(), &m_ListenSet);
  838. break;
  839. case BMON_NOWAIT:
  840. //
  841. // this entry is paused, so don't do
  842. // anything
  843. //
  844. break;
  845. default:
  846. //
  847. // should never get here
  848. // remove the bad entry
  849. //
  850. DBGPRINTF((DBG_CONTEXT,
  851. "Invalid opcode in ATQ_BMON_ENTRY %p, %d\n",
  852. pBmonEntry, pBmonEntry->GetOpcode()));
  853. DBG_ASSERT(FALSE);
  854. m_apEntrySet[i] = NULL;
  855. break;
  856. }
  857. }
  858. }
  859. Unlock();
  860. return bRetval;
  861. }
  862. BOOL
  863. ATQ_BMON_SET::NotifyEntries(
  864. VOID
  865. )
  866. /*++
  867. Routine Description:
  868. This function looks through the entries
  869. to see who needs to be notified and calls
  870. their callback function.
  871. Arguments:
  872. None
  873. Return Values:
  874. TRUE if successful, else FALSE
  875. --*/
  876. {
  877. DWORD i;
  878. ATQ_BMON_ENTRY * pBmonEntry;
  879. BOOL fRet = TRUE;
  880. Lock();
  881. for (i = 0; i < FD_SETSIZE; i++) {
  882. pBmonEntry = m_apEntrySet[i];
  883. if (pBmonEntry) {
  884. if (!pBmonEntry->CheckSignature()) {
  885. DBGPRINTF(( DBG_CONTEXT,
  886. "ATQ_BMON_ENTRY(%p)::CheckSignature() failed. index = %d\n",
  887. pBmonEntry, i));
  888. DBG_ASSERT( pBmonEntry->CheckSignature() );
  889. }
  890. if ((pBmonEntry->GetOpcode() == BMON_WAIT)
  891. && (FD_ISSET(pBmonEntry->GetSocket(), &m_ListenSet))) {
  892. if ( !pBmonEntry->Callback() )
  893. {
  894. fRet = FALSE;
  895. break;
  896. }
  897. }
  898. }
  899. }
  900. Unlock();
  901. return fRet;
  902. }
  903. DWORD WINAPI
  904. BmonThreadFunc(
  905. LPVOID lpBmonSet
  906. )
  907. /*++
  908. Routine Description:
  909. This function starts the select thread
  910. of an ATQ_BMON_SET.
  911. Arguments:
  912. pBmonSet - the set to call
  913. Return Values:
  914. 0
  915. --*/
  916. {
  917. ATQ_BMON_SET * pBmonSet = (ATQ_BMON_SET *) lpBmonSet;
  918. pBmonSet->BmonThreadFunc();
  919. return 0;
  920. }
  921. //
  922. // atqbmon.cxx
  923. //