PageRenderTime 26ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/nx-3.5.0/nx-X11/programs/Xserver/Xext/sync.c

#
C | 2513 lines | 1832 code | 357 blank | 324 comment | 254 complexity | f9585f0aec1bc54673ad60f6a7788a43 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /* $Xorg: sync.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
  2. /*
  3. Copyright 1991, 1993, 1998 The Open Group
  4. Permission to use, copy, modify, distribute, and sell this software and its
  5. documentation for any purpose is hereby granted without fee, provided that
  6. the above copyright notice appear in all copies and that both that
  7. copyright notice and this permission notice appear in supporting
  8. documentation.
  9. The above copyright notice and this permission notice shall be included
  10. in all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  12. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  13. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  14. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
  15. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  16. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  17. OTHER DEALINGS IN THE SOFTWARE.
  18. Except as contained in this notice, the name of The Open Group shall
  19. not be used in advertising or otherwise to promote the sale, use or
  20. other dealings in this Software without prior written authorization
  21. from The Open Group.
  22. Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
  23. and Olivetti Research Limited, Cambridge, England.
  24. All Rights Reserved
  25. Permission to use, copy, modify, and distribute this software and its
  26. documentation for any purpose and without fee is hereby granted,
  27. provided that the above copyright notice appear in all copies and that
  28. both that copyright notice and this permission notice appear in
  29. supporting documentation, and that the names of Digital or Olivetti
  30. not be used in advertising or publicity pertaining to distribution of the
  31. software without specific, written prior permission. Digital and Olivetti
  32. make no representations about the suitability of this software
  33. for any purpose. It is provided "as is" without express or implied warranty.
  34. DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  35. SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  36. FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  37. CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  38. USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  39. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  40. PERFORMANCE OF THIS SOFTWARE.
  41. */
  42. /* $XFree86: xc/programs/Xserver/Xext/sync.c,v 3.13 2003/09/02 18:19:01 tsi Exp $ */
  43. #define NEED_REPLIES
  44. #define NEED_EVENTS
  45. #ifdef HAVE_DIX_CONFIG_H
  46. #include <dix-config.h>
  47. #endif
  48. #include <X11/X.h>
  49. #include <X11/Xproto.h>
  50. #include <X11/Xmd.h>
  51. #include "misc.h"
  52. #include "os.h"
  53. #include "extnsionst.h"
  54. #include "dixstruct.h"
  55. #include "resource.h"
  56. #include "opaque.h"
  57. #define _SYNC_SERVER
  58. #include <X11/extensions/sync.h>
  59. #include <X11/extensions/syncstr.h>
  60. #ifdef EXTMODULE
  61. #include "xf86_ansic.h"
  62. #else
  63. #include <stdio.h>
  64. #if !defined(WIN32) && !defined(Lynx)
  65. #include <sys/time.h>
  66. #endif
  67. #endif
  68. #include "modinit.h"
  69. /*
  70. * Local Global Variables
  71. */
  72. static int SyncEventBase;
  73. static int SyncErrorBase;
  74. static RESTYPE RTCounter = 0;
  75. static RESTYPE RTAwait;
  76. static RESTYPE RTAlarm;
  77. static RESTYPE RTAlarmClient;
  78. static int SyncNumSystemCounters = 0;
  79. static SyncCounter **SysCounterList = NULL;
  80. #define IsSystemCounter(pCounter) \
  81. (pCounter && (pCounter->client == NULL))
  82. /* these are all the alarm attributes that pertain to the alarm's trigger */
  83. #define XSyncCAAllTrigger \
  84. (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
  85. static int
  86. FreeAlarm(
  87. pointer /* addr */,
  88. XID /* id */
  89. );
  90. static int
  91. FreeAlarmClient(
  92. pointer /* value */,
  93. XID /* id */
  94. );
  95. static int
  96. FreeAwait(
  97. pointer /* addr */,
  98. XID /* id */
  99. );
  100. static void
  101. ServertimeBracketValues(
  102. pointer /* pCounter */,
  103. CARD64 * /* pbracket_less */,
  104. CARD64 * /* pbracket_greater */
  105. );
  106. static void
  107. ServertimeQueryValue(
  108. pointer /* pCounter */,
  109. CARD64 * /* pValue_return */
  110. );
  111. static void
  112. ServertimeWakeupHandler(
  113. pointer /* env */,
  114. int /* rc */,
  115. pointer /* LastSelectMask */
  116. );
  117. static int
  118. SyncInitTrigger(
  119. ClientPtr /* client */,
  120. SyncTrigger * /* pTrigger */,
  121. XSyncCounter /* counter */,
  122. Mask /* changes */
  123. );
  124. static void
  125. SAlarmNotifyEvent(
  126. xSyncAlarmNotifyEvent * /* from */,
  127. xSyncAlarmNotifyEvent * /* to */
  128. );
  129. static void
  130. SCounterNotifyEvent(
  131. xSyncCounterNotifyEvent * /* from */,
  132. xSyncCounterNotifyEvent * /* to */
  133. );
  134. static void
  135. ServertimeBlockHandler(
  136. pointer /* env */,
  137. struct timeval ** /* wt */,
  138. pointer /* LastSelectMask */
  139. );
  140. static int
  141. SyncAddTriggerToCounter(
  142. SyncTrigger * /* pTrigger */
  143. );
  144. extern void
  145. SyncAlarmCounterDestroyed(
  146. SyncTrigger * /* pTrigger */
  147. );
  148. static void
  149. SyncAlarmTriggerFired(
  150. SyncTrigger * /* pTrigger */
  151. );
  152. static void
  153. SyncAwaitTriggerFired(
  154. SyncTrigger * /* pTrigger */
  155. );
  156. static int
  157. SyncChangeAlarmAttributes(
  158. ClientPtr /* client */,
  159. SyncAlarm * /* pAlarm */,
  160. Mask /* mask */,
  161. CARD32 * /* values */
  162. );
  163. static Bool
  164. SyncCheckTriggerNegativeComparison(
  165. SyncTrigger * /* pTrigger */,
  166. CARD64 /* oldval */
  167. );
  168. static Bool
  169. SyncCheckTriggerNegativeTransition(
  170. SyncTrigger * /* pTrigger */,
  171. CARD64 /* oldval */
  172. );
  173. static Bool
  174. SyncCheckTriggerPositiveComparison(
  175. SyncTrigger * /* pTrigger */,
  176. CARD64 /* oldval */
  177. );
  178. static Bool
  179. SyncCheckTriggerPositiveTransition(
  180. SyncTrigger * /* pTrigger */,
  181. CARD64 /* oldval */
  182. );
  183. static SyncCounter *
  184. SyncCreateCounter(
  185. ClientPtr /* client */,
  186. XSyncCounter /* id */,
  187. CARD64 /* initialvalue */
  188. );
  189. static void SyncComputeBracketValues(
  190. SyncCounter * /* pCounter */,
  191. Bool /* startOver */
  192. );
  193. static void
  194. SyncDeleteTriggerFromCounter(
  195. SyncTrigger * /* pTrigger */
  196. );
  197. static Bool
  198. SyncEventSelectForAlarm(
  199. SyncAlarm * /* pAlarm */,
  200. ClientPtr /* client */,
  201. Bool /* wantevents */
  202. );
  203. static void
  204. SyncInitServerTime(
  205. void
  206. );
  207. static void
  208. SyncResetProc(
  209. ExtensionEntry * /* extEntry */
  210. );
  211. static void
  212. SyncSendAlarmNotifyEvents(
  213. SyncAlarm * /* pAlarm */
  214. );
  215. static void
  216. SyncSendCounterNotifyEvents(
  217. ClientPtr /* client */,
  218. SyncAwait ** /* ppAwait */,
  219. int /* num_events */
  220. );
  221. static DISPATCH_PROC(ProcSyncAwait);
  222. static DISPATCH_PROC(ProcSyncChangeAlarm);
  223. static DISPATCH_PROC(ProcSyncChangeCounter);
  224. static DISPATCH_PROC(ProcSyncCreateAlarm);
  225. static DISPATCH_PROC(ProcSyncCreateCounter);
  226. static DISPATCH_PROC(ProcSyncDestroyAlarm);
  227. static DISPATCH_PROC(ProcSyncDestroyCounter);
  228. static DISPATCH_PROC(ProcSyncDispatch);
  229. static DISPATCH_PROC(ProcSyncGetPriority);
  230. static DISPATCH_PROC(ProcSyncInitialize);
  231. static DISPATCH_PROC(ProcSyncListSystemCounters);
  232. static DISPATCH_PROC(ProcSyncQueryAlarm);
  233. static DISPATCH_PROC(ProcSyncQueryCounter);
  234. static DISPATCH_PROC(ProcSyncSetCounter);
  235. static DISPATCH_PROC(ProcSyncSetPriority);
  236. static DISPATCH_PROC(SProcSyncAwait);
  237. static DISPATCH_PROC(SProcSyncChangeAlarm);
  238. static DISPATCH_PROC(SProcSyncChangeCounter);
  239. static DISPATCH_PROC(SProcSyncCreateAlarm);
  240. static DISPATCH_PROC(SProcSyncCreateCounter);
  241. static DISPATCH_PROC(SProcSyncDestroyAlarm);
  242. static DISPATCH_PROC(SProcSyncDestroyCounter);
  243. static DISPATCH_PROC(SProcSyncDispatch);
  244. static DISPATCH_PROC(SProcSyncGetPriority);
  245. static DISPATCH_PROC(SProcSyncInitialize);
  246. static DISPATCH_PROC(SProcSyncListSystemCounters);
  247. static DISPATCH_PROC(SProcSyncQueryAlarm);
  248. static DISPATCH_PROC(SProcSyncQueryCounter);
  249. static DISPATCH_PROC(SProcSyncSetCounter);
  250. static DISPATCH_PROC(SProcSyncSetPriority);
  251. /* Each counter maintains a simple linked list of triggers that are
  252. * interested in the counter. The two functions below are used to
  253. * delete and add triggers on this list.
  254. */
  255. static void
  256. SyncDeleteTriggerFromCounter(pTrigger)
  257. SyncTrigger *pTrigger;
  258. {
  259. SyncTriggerList *pCur, *pPrev = NULL;
  260. /* pCounter needs to be stored in pTrigger before calling here. */
  261. if (!pTrigger->pCounter)
  262. return;
  263. for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
  264. {
  265. if (pCur->pTrigger == pTrigger)
  266. {
  267. if (pPrev)
  268. pPrev->next = pCur->next;
  269. else
  270. pTrigger->pCounter->pTriglist = pCur->next;
  271. xfree(pCur);
  272. break;
  273. }
  274. }
  275. if (IsSystemCounter(pTrigger->pCounter))
  276. SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
  277. }
  278. static int
  279. SyncAddTriggerToCounter(pTrigger)
  280. SyncTrigger *pTrigger;
  281. {
  282. SyncTriggerList *pCur;
  283. if (!pTrigger->pCounter)
  284. return Success;
  285. /* don't do anything if it's already there */
  286. for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
  287. {
  288. if (pCur->pTrigger == pTrigger)
  289. return Success;
  290. }
  291. if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList))))
  292. return BadAlloc;
  293. pCur->pTrigger = pTrigger;
  294. pCur->next = pTrigger->pCounter->pTriglist;
  295. pTrigger->pCounter->pTriglist = pCur;
  296. if (IsSystemCounter(pTrigger->pCounter))
  297. SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
  298. return Success;
  299. }
  300. /* Below are four possible functions that can be plugged into
  301. * pTrigger->CheckTrigger, corresponding to the four possible
  302. * test-types. These functions are called after the counter's
  303. * value changes but are also passed the old counter value
  304. * so they can inspect both the old and new values.
  305. * (PositiveTransition and NegativeTransition need to see both
  306. * pieces of information.) These functions return the truth value
  307. * of the trigger.
  308. *
  309. * All of them include the condition pTrigger->pCounter == NULL.
  310. * This is because the spec says that a trigger with a counter value
  311. * of None is always TRUE.
  312. */
  313. static Bool
  314. SyncCheckTriggerPositiveComparison(pTrigger, oldval)
  315. SyncTrigger *pTrigger;
  316. CARD64 oldval;
  317. {
  318. return (pTrigger->pCounter == NULL ||
  319. XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
  320. pTrigger->test_value));
  321. }
  322. static Bool
  323. SyncCheckTriggerNegativeComparison(pTrigger, oldval)
  324. SyncTrigger *pTrigger;
  325. CARD64 oldval;
  326. {
  327. return (pTrigger->pCounter == NULL ||
  328. XSyncValueLessOrEqual(pTrigger->pCounter->value,
  329. pTrigger->test_value));
  330. }
  331. static Bool
  332. SyncCheckTriggerPositiveTransition(pTrigger, oldval)
  333. SyncTrigger *pTrigger;
  334. CARD64 oldval;
  335. {
  336. return (pTrigger->pCounter == NULL ||
  337. (XSyncValueLessThan(oldval, pTrigger->test_value) &&
  338. XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
  339. pTrigger->test_value)));
  340. }
  341. static Bool
  342. SyncCheckTriggerNegativeTransition(pTrigger, oldval)
  343. SyncTrigger *pTrigger;
  344. CARD64 oldval;
  345. {
  346. return (pTrigger->pCounter == NULL ||
  347. (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
  348. XSyncValueLessOrEqual(pTrigger->pCounter->value,
  349. pTrigger->test_value)));
  350. }
  351. static int
  352. SyncInitTrigger(client, pTrigger, counter, changes)
  353. ClientPtr client; /* so we can set errorValue */
  354. SyncTrigger *pTrigger;
  355. XSyncCounter counter;
  356. Mask changes;
  357. {
  358. SyncCounter *pCounter = pTrigger->pCounter;
  359. int status;
  360. Bool newcounter = FALSE;
  361. if (changes & XSyncCACounter)
  362. {
  363. if (counter == None)
  364. pCounter = NULL;
  365. else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType(
  366. client, counter, RTCounter, SecurityReadAccess)))
  367. {
  368. client->errorValue = counter;
  369. return SyncErrorBase + XSyncBadCounter;
  370. }
  371. if (pCounter != pTrigger->pCounter)
  372. { /* new counter for trigger */
  373. SyncDeleteTriggerFromCounter(pTrigger);
  374. pTrigger->pCounter = pCounter;
  375. newcounter = TRUE;
  376. }
  377. }
  378. /* if system counter, ask it what the current value is */
  379. if (IsSystemCounter(pCounter))
  380. {
  381. (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
  382. &pCounter->value);
  383. }
  384. if (changes & XSyncCAValueType)
  385. {
  386. if (pTrigger->value_type != XSyncRelative &&
  387. pTrigger->value_type != XSyncAbsolute)
  388. {
  389. client->errorValue = pTrigger->value_type;
  390. return BadValue;
  391. }
  392. }
  393. if (changes & XSyncCATestType)
  394. {
  395. if (pTrigger->test_type != XSyncPositiveTransition &&
  396. pTrigger->test_type != XSyncNegativeTransition &&
  397. pTrigger->test_type != XSyncPositiveComparison &&
  398. pTrigger->test_type != XSyncNegativeComparison)
  399. {
  400. client->errorValue = pTrigger->test_type;
  401. return BadValue;
  402. }
  403. /* select appropriate CheckTrigger function */
  404. switch (pTrigger->test_type)
  405. {
  406. case XSyncPositiveTransition:
  407. pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
  408. break;
  409. case XSyncNegativeTransition:
  410. pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
  411. break;
  412. case XSyncPositiveComparison:
  413. pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
  414. break;
  415. case XSyncNegativeComparison:
  416. pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
  417. break;
  418. }
  419. }
  420. if (changes & (XSyncCAValueType | XSyncCAValue))
  421. {
  422. if (pTrigger->value_type == XSyncAbsolute)
  423. pTrigger->test_value = pTrigger->wait_value;
  424. else /* relative */
  425. {
  426. Bool overflow;
  427. if (pCounter == NULL)
  428. return BadMatch;
  429. XSyncValueAdd(&pTrigger->test_value, pCounter->value,
  430. pTrigger->wait_value, &overflow);
  431. if (overflow)
  432. {
  433. client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
  434. return BadValue;
  435. }
  436. }
  437. }
  438. /* we wait until we're sure there are no errors before registering
  439. * a new counter on a trigger
  440. */
  441. if (newcounter)
  442. {
  443. if ((status = SyncAddTriggerToCounter(pTrigger)) != Success)
  444. return status;
  445. }
  446. else if (IsSystemCounter(pCounter))
  447. {
  448. SyncComputeBracketValues(pCounter, /*startOver*/ TRUE);
  449. }
  450. return Success;
  451. }
  452. /* AlarmNotify events happen in response to actions taken on an Alarm or
  453. * the counter used by the alarm. AlarmNotify may be sent to multiple
  454. * clients. The alarm maintains a list of clients interested in events.
  455. */
  456. static void
  457. SyncSendAlarmNotifyEvents(pAlarm)
  458. SyncAlarm *pAlarm;
  459. {
  460. SyncAlarmClientList *pcl;
  461. xSyncAlarmNotifyEvent ane;
  462. SyncTrigger *pTrigger = &pAlarm->trigger;
  463. UpdateCurrentTime();
  464. ane.type = SyncEventBase + XSyncAlarmNotify;
  465. ane.kind = XSyncAlarmNotify;
  466. ane.sequenceNumber = pAlarm->client->sequence;
  467. ane.alarm = pAlarm->alarm_id;
  468. if (pTrigger->pCounter)
  469. {
  470. ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
  471. ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
  472. }
  473. else
  474. { /* XXX what else can we do if there's no counter? */
  475. ane.counter_value_hi = ane.counter_value_lo = 0;
  476. }
  477. ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value);
  478. ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value);
  479. ane.time = currentTime.milliseconds;
  480. ane.state = pAlarm->state;
  481. /* send to owner */
  482. if (pAlarm->events && !pAlarm->client->clientGone)
  483. WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
  484. /* send to other interested clients */
  485. for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
  486. {
  487. if (!pAlarm->client->clientGone)
  488. {
  489. ane.sequenceNumber = pcl->client->sequence;
  490. WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
  491. }
  492. }
  493. }
  494. /* CounterNotify events only occur in response to an Await. The events
  495. * go only to the Awaiting client.
  496. */
  497. static void
  498. SyncSendCounterNotifyEvents(client, ppAwait, num_events)
  499. ClientPtr client;
  500. SyncAwait **ppAwait;
  501. int num_events;
  502. {
  503. xSyncCounterNotifyEvent *pEvents, *pev;
  504. int i;
  505. if (client->clientGone)
  506. return;
  507. pev = pEvents = (xSyncCounterNotifyEvent *)
  508. ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent));
  509. if (!pEvents)
  510. return;
  511. UpdateCurrentTime();
  512. for (i = 0; i < num_events; i++, ppAwait++, pev++)
  513. {
  514. SyncTrigger *pTrigger = &(*ppAwait)->trigger;
  515. pev->type = SyncEventBase + XSyncCounterNotify;
  516. pev->kind = XSyncCounterNotify;
  517. pev->sequenceNumber = client->sequence;
  518. pev->counter = pTrigger->pCounter->id;
  519. pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
  520. pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
  521. pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
  522. pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
  523. pev->time = currentTime.milliseconds;
  524. pev->count = num_events - i - 1; /* events remaining */
  525. pev->destroyed = pTrigger->pCounter->beingDestroyed;
  526. }
  527. /* swapping will be taken care of by this */
  528. WriteEventsToClient(client, num_events, (xEvent *)pEvents);
  529. DEALLOCATE_LOCAL(pEvents);
  530. }
  531. /* This function is called when an alarm's counter is destroyed.
  532. * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
  533. */
  534. void
  535. SyncAlarmCounterDestroyed(pTrigger)
  536. SyncTrigger *pTrigger;
  537. {
  538. SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
  539. pAlarm->state = XSyncAlarmInactive;
  540. SyncSendAlarmNotifyEvents(pAlarm);
  541. pTrigger->pCounter = NULL;
  542. }
  543. /* This function is called when an alarm "goes off."
  544. * It is plugged into pTrigger->TriggerFired (for alarm triggers).
  545. */
  546. static void
  547. SyncAlarmTriggerFired(pTrigger)
  548. SyncTrigger *pTrigger;
  549. {
  550. SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
  551. CARD64 new_test_value;
  552. /* no need to check alarm unless it's active */
  553. if (pAlarm->state != XSyncAlarmActive)
  554. return;
  555. /* " if the counter value is None, or if the delta is 0 and
  556. * the test-type is PositiveComparison or NegativeComparison,
  557. * no change is made to value (test-value) and the alarm
  558. * state is changed to Inactive before the event is generated."
  559. */
  560. if (pAlarm->trigger.pCounter == NULL
  561. || (XSyncValueIsZero(pAlarm->delta)
  562. && (pAlarm->trigger.test_type == XSyncPositiveComparison
  563. || pAlarm->trigger.test_type == XSyncNegativeComparison)))
  564. pAlarm->state = XSyncAlarmInactive;
  565. new_test_value = pAlarm->trigger.test_value;
  566. if (pAlarm->state == XSyncAlarmActive)
  567. {
  568. Bool overflow;
  569. CARD64 oldvalue;
  570. SyncTrigger *paTrigger = &pAlarm->trigger;
  571. /* "The alarm is updated by repeatedly adding delta to the
  572. * value of the trigger and re-initializing it until it
  573. * becomes FALSE."
  574. */
  575. oldvalue = paTrigger->test_value;
  576. /* XXX really should do something smarter here */
  577. do
  578. {
  579. XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
  580. pAlarm->delta, &overflow);
  581. } while (!overflow &&
  582. (*paTrigger->CheckTrigger)(paTrigger,
  583. paTrigger->pCounter->value));
  584. new_test_value = paTrigger->test_value;
  585. paTrigger->test_value = oldvalue;
  586. /* "If this update would cause value to fall outside the range
  587. * for an INT64...no change is made to value (test-value) and
  588. * the alarm state is changed to Inactive before the event is
  589. * generated."
  590. */
  591. if (overflow)
  592. {
  593. new_test_value = oldvalue;
  594. pAlarm->state = XSyncAlarmInactive;
  595. }
  596. }
  597. /* The AlarmNotify event has to have the "new state of the alarm"
  598. * which we can't be sure of until this point. However, it has
  599. * to have the "old" trigger test value. That's the reason for
  600. * all the newvalue/oldvalue shuffling above. After we send the
  601. * events, give the trigger its new test value.
  602. */
  603. SyncSendAlarmNotifyEvents(pAlarm);
  604. pTrigger->test_value = new_test_value;
  605. }
  606. /* This function is called when an Await unblocks, either as a result
  607. * of the trigger firing OR the counter being destroyed.
  608. * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
  609. * (for Await triggers).
  610. */
  611. static void
  612. SyncAwaitTriggerFired(pTrigger)
  613. SyncTrigger *pTrigger;
  614. {
  615. SyncAwait *pAwait = (SyncAwait *)pTrigger;
  616. int numwaits;
  617. SyncAwaitUnion *pAwaitUnion;
  618. SyncAwait **ppAwait;
  619. int num_events = 0;
  620. pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
  621. numwaits = pAwaitUnion->header.num_waitconditions;
  622. ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *));
  623. if (!ppAwait)
  624. goto bail;
  625. pAwait = &(pAwaitUnion+1)->await;
  626. /* "When a client is unblocked, all the CounterNotify events for
  627. * the Await request are generated contiguously. If count is 0
  628. * there are no more events to follow for this request. If
  629. * count is n, there are at least n more events to follow."
  630. *
  631. * Thus, it is best to find all the counters for which events
  632. * need to be sent first, so that an accurate count field can
  633. * be stored in the events.
  634. */
  635. for ( ; numwaits; numwaits--, pAwait++)
  636. {
  637. CARD64 diff;
  638. Bool overflow, diffgreater, diffequal;
  639. /* "A CounterNotify event with the destroyed flag set to TRUE is
  640. * always generated if the counter for one of the triggers is
  641. * destroyed."
  642. */
  643. if (pAwait->trigger.pCounter->beingDestroyed)
  644. {
  645. ppAwait[num_events++] = pAwait;
  646. continue;
  647. }
  648. /* "The difference between the counter and the test value is
  649. * calculated by subtracting the test value from the value of
  650. * the counter."
  651. */
  652. XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value,
  653. pAwait->trigger.test_value, &overflow);
  654. /* "If the difference lies outside the range for an INT64, an
  655. * event is not generated."
  656. */
  657. if (overflow)
  658. continue;
  659. diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
  660. diffequal = XSyncValueEqual(diff, pAwait->event_threshold);
  661. /* "If the test-type is PositiveTransition or
  662. * PositiveComparison, a CounterNotify event is generated if
  663. * the difference is at least event-threshold. If the test-type
  664. * is NegativeTransition or NegativeComparison, a CounterNotify
  665. * event is generated if the difference is at most
  666. * event-threshold."
  667. */
  668. if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
  669. pAwait->trigger.test_type == XSyncPositiveTransition)
  670. && (diffgreater || diffequal))
  671. ||
  672. ((pAwait->trigger.test_type == XSyncNegativeComparison ||
  673. pAwait->trigger.test_type == XSyncNegativeTransition)
  674. && (!diffgreater) /* less or equal */
  675. )
  676. )
  677. {
  678. ppAwait[num_events++] = pAwait;
  679. }
  680. }
  681. if (num_events)
  682. SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
  683. num_events);
  684. DEALLOCATE_LOCAL(ppAwait);
  685. bail:
  686. /* unblock the client */
  687. AttendClient(pAwaitUnion->header.client);
  688. /* delete the await */
  689. FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
  690. }
  691. /* This function should always be used to change a counter's value so that
  692. * any triggers depending on the counter will be checked.
  693. */
  694. void
  695. SyncChangeCounter(pCounter, newval)
  696. SyncCounter *pCounter;
  697. CARD64 newval;
  698. {
  699. SyncTriggerList *ptl, *pnext;
  700. CARD64 oldval;
  701. oldval = pCounter->value;
  702. pCounter->value = newval;
  703. /* run through triggers to see if any become true */
  704. for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
  705. {
  706. pnext = ptl->next;
  707. if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
  708. (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
  709. }
  710. if (IsSystemCounter(pCounter))
  711. {
  712. SyncComputeBracketValues(pCounter, /* startOver */ FALSE);
  713. }
  714. }
  715. /* loosely based on dix/events.c/EventSelectForWindow */
  716. static Bool
  717. SyncEventSelectForAlarm(pAlarm, client, wantevents)
  718. SyncAlarm *pAlarm;
  719. ClientPtr client;
  720. Bool wantevents;
  721. {
  722. SyncAlarmClientList *pClients;
  723. if (client == pAlarm->client) /* alarm owner */
  724. {
  725. pAlarm->events = wantevents;
  726. return Success;
  727. }
  728. /* see if the client is already on the list (has events selected) */
  729. for (pClients = pAlarm->pEventClients; pClients;
  730. pClients = pClients->next)
  731. {
  732. if (pClients->client == client)
  733. {
  734. /* client's presence on the list indicates desire for
  735. * events. If the client doesn't want events, remove it
  736. * from the list. If the client does want events, do
  737. * nothing, since it's already got them.
  738. */
  739. if (!wantevents)
  740. {
  741. FreeResource(pClients->delete_id, RT_NONE);
  742. }
  743. return Success;
  744. }
  745. }
  746. /* if we get here, this client does not currently have
  747. * events selected on the alarm
  748. */
  749. if (!wantevents)
  750. /* client doesn't want events, and we just discovered that it
  751. * doesn't have them, so there's nothing to do.
  752. */
  753. return Success;
  754. /* add new client to pAlarm->pEventClients */
  755. pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList));
  756. if (!pClients)
  757. return BadAlloc;
  758. /* register it as a resource so it will be cleaned up
  759. * if the client dies
  760. */
  761. pClients->delete_id = FakeClientID(client->index);
  762. if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
  763. {
  764. xfree(pClients);
  765. return BadAlloc;
  766. }
  767. /* link it into list after we know all the allocations succeed */
  768. pClients->next = pAlarm->pEventClients;
  769. pAlarm->pEventClients = pClients;
  770. pClients->client = client;
  771. return Success;
  772. }
  773. /*
  774. * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
  775. */
  776. static int
  777. SyncChangeAlarmAttributes(client, pAlarm, mask, values)
  778. ClientPtr client;
  779. SyncAlarm *pAlarm;
  780. Mask mask;
  781. CARD32 *values;
  782. {
  783. int status;
  784. XSyncCounter counter;
  785. Mask origmask = mask;
  786. counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None;
  787. while (mask)
  788. {
  789. int index2 = lowbit(mask);
  790. mask &= ~index2;
  791. switch (index2)
  792. {
  793. case XSyncCACounter:
  794. mask &= ~XSyncCACounter;
  795. /* sanity check in SyncInitTrigger */
  796. counter = *values++;
  797. break;
  798. case XSyncCAValueType:
  799. mask &= ~XSyncCAValueType;
  800. /* sanity check in SyncInitTrigger */
  801. pAlarm->trigger.value_type = *values++;
  802. break;
  803. case XSyncCAValue:
  804. mask &= ~XSyncCAValue;
  805. XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
  806. values += 2;
  807. break;
  808. case XSyncCATestType:
  809. mask &= ~XSyncCATestType;
  810. /* sanity check in SyncInitTrigger */
  811. pAlarm->trigger.test_type = *values++;
  812. break;
  813. case XSyncCADelta:
  814. mask &= ~XSyncCADelta;
  815. XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
  816. values += 2;
  817. break;
  818. case XSyncCAEvents:
  819. mask &= ~XSyncCAEvents;
  820. if ((*values != xTrue) && (*values != xFalse))
  821. {
  822. client->errorValue = *values;
  823. return BadValue;
  824. }
  825. status = SyncEventSelectForAlarm(pAlarm, client,
  826. (Bool)(*values++));
  827. if (status != Success)
  828. return status;
  829. break;
  830. default:
  831. client->errorValue = mask;
  832. return BadValue;
  833. }
  834. }
  835. /* "If the test-type is PositiveComparison or PositiveTransition
  836. * and delta is less than zero, or if the test-type is
  837. * NegativeComparison or NegativeTransition and delta is
  838. * greater than zero, a Match error is generated."
  839. */
  840. if (origmask & (XSyncCADelta|XSyncCATestType))
  841. {
  842. CARD64 zero;
  843. XSyncIntToValue(&zero, 0);
  844. if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
  845. (pAlarm->trigger.test_type == XSyncPositiveTransition))
  846. && XSyncValueLessThan(pAlarm->delta, zero))
  847. ||
  848. (((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
  849. (pAlarm->trigger.test_type == XSyncNegativeTransition))
  850. && XSyncValueGreaterThan(pAlarm->delta, zero))
  851. )
  852. {
  853. return BadMatch;
  854. }
  855. }
  856. /* postpone this until now, when we're sure nothing else can go wrong */
  857. if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter,
  858. origmask & XSyncCAAllTrigger)) != Success)
  859. return status;
  860. /* XXX spec does not really say to do this - needs clarification */
  861. pAlarm->state = XSyncAlarmActive;
  862. return Success;
  863. }
  864. static SyncCounter *
  865. SyncCreateCounter(client, id, initialvalue)
  866. ClientPtr client;
  867. XSyncCounter id;
  868. CARD64 initialvalue;
  869. {
  870. SyncCounter *pCounter;
  871. if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter))))
  872. return (SyncCounter *)NULL;
  873. if (!AddResource(id, RTCounter, (pointer) pCounter))
  874. {
  875. xfree((pointer) pCounter);
  876. return (SyncCounter *)NULL;
  877. }
  878. pCounter->client = client;
  879. pCounter->id = id;
  880. pCounter->value = initialvalue;
  881. pCounter->pTriglist = NULL;
  882. pCounter->beingDestroyed = FALSE;
  883. pCounter->pSysCounterInfo = NULL;
  884. return pCounter;
  885. }
  886. static int FreeCounter(
  887. pointer /*env*/,
  888. XID /*id*/
  889. );
  890. /*
  891. * ***** System Counter utilities
  892. */
  893. pointer
  894. SyncCreateSystemCounter(name, initial, resolution, counterType,
  895. QueryValue, BracketValues)
  896. char *name;
  897. CARD64 initial;
  898. CARD64 resolution;
  899. SyncCounterType counterType;
  900. void (*QueryValue) (
  901. pointer /* pCounter */,
  902. CARD64 * /* pValue_return */);
  903. void (*BracketValues) (
  904. pointer /* pCounter */,
  905. CARD64 * /* pbracket_less */,
  906. CARD64 * /* pbracket_greater */);
  907. {
  908. SyncCounter *pCounter;
  909. SysCounterList = (SyncCounter **)xrealloc(SysCounterList,
  910. (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
  911. if (!SysCounterList)
  912. return (pointer)NULL;
  913. /* this function may be called before SYNC has been initialized, so we
  914. * have to make sure RTCounter is created.
  915. */
  916. if (RTCounter == 0)
  917. {
  918. RTCounter = CreateNewResourceType(FreeCounter);
  919. if (RTCounter == 0)
  920. {
  921. return (pointer)NULL;
  922. }
  923. }
  924. pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial);
  925. if (pCounter)
  926. {
  927. SysCounterInfo *psci;
  928. psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo));
  929. if (!psci)
  930. {
  931. FreeResource(pCounter->id, RT_NONE);
  932. return (pointer) pCounter;
  933. }
  934. pCounter->pSysCounterInfo = psci;
  935. psci->name = name;
  936. psci->resolution = resolution;
  937. psci->counterType = counterType;
  938. psci->QueryValue = QueryValue;
  939. psci->BracketValues = BracketValues;
  940. XSyncMaxValue(&psci->bracket_greater);
  941. XSyncMinValue(&psci->bracket_less);
  942. SysCounterList[SyncNumSystemCounters++] = pCounter;
  943. }
  944. return (pointer) pCounter;
  945. }
  946. void
  947. SyncDestroySystemCounter(pSysCounter)
  948. pointer pSysCounter;
  949. {
  950. SyncCounter *pCounter = (SyncCounter *)pSysCounter;
  951. FreeResource(pCounter->id, RT_NONE);
  952. }
  953. static void
  954. SyncComputeBracketValues(pCounter, startOver)
  955. SyncCounter *pCounter;
  956. Bool startOver;
  957. {
  958. SyncTriggerList *pCur;
  959. SyncTrigger *pTrigger;
  960. SysCounterInfo *psci = pCounter->pSysCounterInfo;
  961. CARD64 *pnewgtval = NULL;
  962. CARD64 *pnewltval = NULL;
  963. SyncCounterType ct;
  964. if (!pCounter)
  965. return;
  966. ct = pCounter->pSysCounterInfo->counterType;
  967. if (ct == XSyncCounterNeverChanges)
  968. return;
  969. if (startOver)
  970. {
  971. XSyncMaxValue(&psci->bracket_greater);
  972. XSyncMinValue(&psci->bracket_less);
  973. }
  974. for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next)
  975. {
  976. pTrigger = pCur->pTrigger;
  977. if (pTrigger->test_type == XSyncPositiveComparison &&
  978. ct != XSyncCounterNeverIncreases)
  979. {
  980. if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
  981. XSyncValueLessThan(pTrigger->test_value,
  982. psci->bracket_greater))
  983. {
  984. psci->bracket_greater = pTrigger->test_value;
  985. pnewgtval = &psci->bracket_greater;
  986. }
  987. }
  988. else if (pTrigger->test_type == XSyncNegativeComparison &&
  989. ct != XSyncCounterNeverDecreases)
  990. {
  991. if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
  992. XSyncValueGreaterThan(pTrigger->test_value,
  993. psci->bracket_less))
  994. {
  995. psci->bracket_less = pTrigger->test_value;
  996. pnewltval = &psci->bracket_less;
  997. }
  998. }
  999. else if ( (pTrigger->test_type == XSyncPositiveTransition &&
  1000. ct != XSyncCounterNeverIncreases)
  1001. ||
  1002. (pTrigger->test_type == XSyncNegativeTransition &&
  1003. ct != XSyncCounterNeverDecreases)
  1004. )
  1005. {
  1006. if (XSyncValueLessThan(pCounter->value, pTrigger->test_value))
  1007. {
  1008. if (XSyncValueLessThan(pTrigger->test_value,
  1009. psci->bracket_greater))
  1010. {
  1011. psci->bracket_greater = pTrigger->test_value;
  1012. pnewgtval = &psci->bracket_greater;
  1013. }
  1014. else
  1015. if (XSyncValueGreaterThan(pTrigger->test_value,
  1016. psci->bracket_less))
  1017. {
  1018. psci->bracket_less = pTrigger->test_value;
  1019. pnewltval = &psci->bracket_less;
  1020. }
  1021. }
  1022. }
  1023. } /* end for each trigger */
  1024. if (pnewgtval || pnewltval)
  1025. {
  1026. (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
  1027. }
  1028. }
  1029. /*
  1030. * ***** Resource delete functions
  1031. */
  1032. /* ARGSUSED */
  1033. static int
  1034. FreeAlarm(addr, id)
  1035. pointer addr;
  1036. XID id;
  1037. {
  1038. SyncAlarm *pAlarm = (SyncAlarm *) addr;
  1039. pAlarm->state = XSyncAlarmDestroyed;
  1040. SyncSendAlarmNotifyEvents(pAlarm);
  1041. /* delete event selections */
  1042. while (pAlarm->pEventClients)
  1043. FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
  1044. SyncDeleteTriggerFromCounter(&pAlarm->trigger);
  1045. xfree(pAlarm);
  1046. return Success;
  1047. }
  1048. /*
  1049. * ** Cleanup after the destruction of a Counter
  1050. */
  1051. /* ARGSUSED */
  1052. static int
  1053. FreeCounter(env, id)
  1054. pointer env;
  1055. XID id;
  1056. {
  1057. SyncCounter *pCounter = (SyncCounter *) env;
  1058. SyncTriggerList *ptl, *pnext;
  1059. pCounter->beingDestroyed = TRUE;
  1060. /* tell all the counter's triggers that the counter has been destroyed */
  1061. for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
  1062. {
  1063. (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
  1064. pnext = ptl->next;
  1065. xfree(ptl); /* destroy the trigger list as we go */
  1066. }
  1067. if (IsSystemCounter(pCounter))
  1068. {
  1069. int i, found = 0;
  1070. xfree(pCounter->pSysCounterInfo);
  1071. /* find the counter in the list of system counters and remove it */
  1072. if (SysCounterList)
  1073. {
  1074. for (i = 0; i < SyncNumSystemCounters; i++)
  1075. {
  1076. if (SysCounterList[i] == pCounter)
  1077. {
  1078. found = i;
  1079. break;
  1080. }
  1081. }
  1082. if (found < (SyncNumSystemCounters-1))
  1083. {
  1084. for (i = found; i < SyncNumSystemCounters-1; i++)
  1085. {
  1086. SysCounterList[i] = SysCounterList[i+1];
  1087. }
  1088. }
  1089. }
  1090. SyncNumSystemCounters--;
  1091. }
  1092. xfree(pCounter);
  1093. return Success;
  1094. }
  1095. /*
  1096. * ** Cleanup after Await
  1097. */
  1098. /* ARGSUSED */
  1099. static int
  1100. FreeAwait(addr, id)
  1101. pointer addr;
  1102. XID id;
  1103. {
  1104. SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
  1105. SyncAwait *pAwait;
  1106. int numwaits;
  1107. pAwait = &(pAwaitUnion+1)->await; /* first await on list */
  1108. /* remove triggers from counters */
  1109. for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
  1110. numwaits--, pAwait++)
  1111. {
  1112. /* If the counter is being destroyed, FreeCounter will delete
  1113. * the trigger list itself, so don't do it here.
  1114. */
  1115. SyncCounter *pCounter = pAwait->trigger.pCounter;
  1116. if (pCounter && !pCounter->beingDestroyed)
  1117. SyncDeleteTriggerFromCounter(&pAwait->trigger);
  1118. }
  1119. xfree(pAwaitUnion);
  1120. return Success;
  1121. }
  1122. /* loosely based on dix/events.c/OtherClientGone */
  1123. static int
  1124. FreeAlarmClient(value, id)
  1125. pointer value; /* must conform to DeleteType */
  1126. XID id;
  1127. {
  1128. SyncAlarm *pAlarm = (SyncAlarm *)value;
  1129. SyncAlarmClientList *pCur, *pPrev;
  1130. for (pPrev = NULL, pCur = pAlarm->pEventClients;
  1131. pCur;
  1132. pPrev = pCur, pCur = pCur->next)
  1133. {
  1134. if (pCur->delete_id == id)
  1135. {
  1136. if (pPrev)
  1137. pPrev->next = pCur->next;
  1138. else
  1139. pAlarm->pEventClients = pCur->next;
  1140. xfree(pCur);
  1141. return(Success);
  1142. }
  1143. }
  1144. FatalError("alarm client not on event list");
  1145. /*NOTREACHED*/
  1146. }
  1147. /*
  1148. * ***** Proc functions
  1149. */
  1150. /*
  1151. * ** Initialize the extension
  1152. */
  1153. static int
  1154. ProcSyncInitialize(client)
  1155. ClientPtr client;
  1156. {
  1157. xSyncInitializeReply rep;
  1158. int n;
  1159. REQUEST_SIZE_MATCH(xSyncInitializeReq);
  1160. rep.type = X_Reply;
  1161. rep.sequenceNumber = client->sequence;
  1162. rep.majorVersion = SYNC_MAJOR_VERSION;
  1163. rep.minorVersion = SYNC_MINOR_VERSION;
  1164. rep.length = 0;
  1165. if (client->swapped)
  1166. {
  1167. swaps(&rep.sequenceNumber, n);
  1168. }
  1169. WriteToClient(client, sizeof(rep), (char *) &rep);
  1170. return (client->noClientException);
  1171. }
  1172. /*
  1173. * ** Get list of system counters available through the extension
  1174. */
  1175. static int
  1176. ProcSyncListSystemCounters(client)
  1177. ClientPtr client;
  1178. {
  1179. xSyncListSystemCountersReply rep;
  1180. int i, len;
  1181. xSyncSystemCounter *list = NULL, *walklist = NULL;
  1182. REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
  1183. rep.type = X_Reply;
  1184. rep.sequenceNumber = client->sequence;
  1185. rep.nCounters = SyncNumSystemCounters;
  1186. for (i = len = 0; i < SyncNumSystemCounters; i++)
  1187. {
  1188. char *name = SysCounterList[i]->pSysCounterInfo->name;
  1189. /* pad to 4 byte boundary */
  1190. len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3;
  1191. }
  1192. if (len)
  1193. {
  1194. walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len);
  1195. if (!list)
  1196. return BadAlloc;
  1197. }
  1198. rep.length = len >> 2;
  1199. if (client->swapped)
  1200. {
  1201. register char n;
  1202. swaps(&rep.sequenceNumber, n);
  1203. swapl(&rep.length, n);
  1204. swapl(&rep.nCounters, n);
  1205. }
  1206. for (i = 0; i < SyncNumSystemCounters; i++)
  1207. {
  1208. int namelen;
  1209. char *pname_in_reply;
  1210. SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
  1211. walklist->counter = SysCounterList[i]->id;
  1212. walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
  1213. walklist->resolution_lo = XSyncValueLow32(psci->resolution);
  1214. namelen = strlen(psci->name);
  1215. walklist->name_length = namelen;
  1216. if (client->swapped)
  1217. {
  1218. register char n;
  1219. swapl(&walklist->counter, n);
  1220. swapl(&walklist->resolution_hi, n);
  1221. swapl(&walklist->resolution_lo, n);
  1222. swaps(&walklist->name_length, n);
  1223. }
  1224. pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter;
  1225. strncpy(pname_in_reply, psci->name, namelen);
  1226. walklist = (xSyncSystemCounter *) (((char *)walklist) +
  1227. ((sz_xSyncSystemCounter + namelen + 3) & ~3));
  1228. }
  1229. WriteToClient(client, sizeof(rep), (char *) &rep);
  1230. if (len)
  1231. {
  1232. WriteToClient(client, len, (char *) list);
  1233. DEALLOCATE_LOCAL(list);
  1234. }
  1235. return (client->noClientException);
  1236. }
  1237. /*
  1238. * ** Set client Priority
  1239. */
  1240. static int
  1241. ProcSyncSetPriority(client)
  1242. ClientPtr client;
  1243. {
  1244. REQUEST(xSyncSetPriorityReq);
  1245. ClientPtr priorityclient;
  1246. REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
  1247. if (stuff->id == None)
  1248. priorityclient = client;
  1249. else if (!(priorityclient = LookupClient(stuff->id, client)))
  1250. {
  1251. client->errorValue = stuff->id;
  1252. return BadMatch;
  1253. }
  1254. if (priorityclient->priority != stuff->priority)
  1255. {
  1256. priorityclient->priority = stuff->priority;
  1257. /* The following will force the server back into WaitForSomething
  1258. * so that the change in this client's priority is immediately
  1259. * reflected.
  1260. */
  1261. isItTimeToYield = TRUE;
  1262. dispatchException |= DE_PRIORITYCHANGE;
  1263. }
  1264. return Success;
  1265. }
  1266. /*
  1267. * ** Get client Priority
  1268. */
  1269. static int
  1270. ProcSyncGetPriority(client)
  1271. ClientPtr client;
  1272. {
  1273. REQUEST(xSyncGetPriorityReq);
  1274. xSyncGetPriorityReply rep;
  1275. ClientPtr priorityclient;
  1276. REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
  1277. if (stuff->id == None)
  1278. priorityclient = client;
  1279. else if (!(priorityclient = LookupClient(stuff->id, client)))
  1280. {
  1281. client->errorValue = stuff->id;
  1282. return BadMatch;
  1283. }
  1284. rep.type = X_Reply;
  1285. rep.length = 0;
  1286. rep.sequenceNumber = client->sequence;
  1287. rep.priority = priorityclient->priority;
  1288. if (client->swapped)
  1289. {
  1290. register char n;
  1291. swaps(&rep.sequenceNumber, n);
  1292. swapl(&rep.priority, n);
  1293. }
  1294. WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
  1295. return (client->noClientException);
  1296. }
  1297. /*
  1298. * ** Create a new counter
  1299. */
  1300. static int
  1301. ProcSyncCreateCounter(client)
  1302. ClientPtr client;
  1303. {
  1304. REQUEST(xSyncCreateCounterReq);
  1305. CARD64 initial;
  1306. REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
  1307. LEGAL_NEW_RESOURCE(stuff->cid, client);
  1308. XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
  1309. if (!SyncCreateCounter(client, stuff->cid, initial))
  1310. return BadAlloc;
  1311. return (client->noClientException);
  1312. }
  1313. /*
  1314. * ** Set Counter value
  1315. */
  1316. static int
  1317. ProcSyncSetCounter(client)
  1318. ClientPtr client;
  1319. {
  1320. REQUEST(xSyncSetCounterReq);
  1321. SyncCounter *pCounter;
  1322. CARD64 newvalue;
  1323. REQUEST_SIZE_MATCH(xSyncSetCounterReq);
  1324. pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid,
  1325. RTCounter, SecurityWriteAccess);
  1326. if (pCounter == NULL)
  1327. {
  1328. client->errorValue = stuff->cid;
  1329. return SyncErrorBase + XSyncBadCounter;
  1330. }
  1331. if (IsSystemCounter(pCounter))
  1332. {
  1333. client->errorValue = stuff->cid;
  1334. return BadAccess;
  1335. }
  1336. XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
  1337. SyncChangeCounter(pCounter, newvalue);
  1338. return Success;
  1339. }
  1340. /*
  1341. * ** Change Counter value
  1342. */
  1343. static int
  1344. ProcSyncChangeCounter(client)
  1345. ClientPtr client;
  1346. {
  1347. REQUEST(xSyncChangeCounterReq);
  1348. SyncCounter *pCounter;
  1349. CARD64 newvalue;
  1350. Bool overflow;
  1351. REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
  1352. pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid,
  1353. RTCounter, SecurityWriteAccess);
  1354. if (pCounter == NULL)
  1355. {
  1356. client->errorValue = stuff->cid;
  1357. return SyncErrorBase + XSyncBadCounter;
  1358. }
  1359. if (IsSystemCounter(pCounter))
  1360. {
  1361. client->errorValue = stuff->cid;
  1362. return BadAccess;
  1363. }
  1364. XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
  1365. XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
  1366. if (overflow)
  1367. {
  1368. /* XXX 64 bit value can't fit in 32 bits; do the best we can */
  1369. client->errorValue = stuff->value_hi;
  1370. return BadValue;
  1371. }
  1372. SyncChangeCounter(pCounter, newvalue);
  1373. return Success;
  1374. }
  1375. /*
  1376. * ** Destroy a counter
  1377. */
  1378. static int
  1379. ProcSyncDestroyCounter(client)
  1380. ClientPtr client;
  1381. {
  1382. REQUEST(xSyncDestroyCounterReq);
  1383. SyncCounter *pCounter;
  1384. REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
  1385. pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
  1386. RTCounter, SecurityDestroyAccess);
  1387. if (pCounter == NULL)
  1388. {
  1389. client->errorValue = stuff->counter;
  1390. return SyncErrorBase + XSyncBadCounter;
  1391. }
  1392. if (IsSystemCounter(pCounter))
  1393. {
  1394. client->errorValue = stuff->counter;
  1395. return BadAccess;
  1396. }
  1397. FreeResource(pCounter->id, RT_NONE);
  1398. return Success;
  1399. }
  1400. /*
  1401. * ** Await
  1402. */
  1403. static int
  1404. ProcSyncAwait(client)
  1405. ClientPtr client;
  1406. {
  1407. REQUEST(xSyncAwaitReq);
  1408. int len, items;
  1409. int i;
  1410. xSyncWaitCondition *pProtocolWaitConds;
  1411. SyncAwaitUnion *pAwaitUnion;
  1412. SyncAwait *pAwait;
  1413. int status;
  1414. REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
  1415. len = client->req_len << 2;
  1416. len -= sz_xSyncAwaitReq;
  1417. items = len / sz_xSyncWaitCondition;
  1418. if (items * sz_xSyncWaitCondition != len)
  1419. {
  1420. return BadLength;
  1421. }
  1422. if (items == 0)
  1423. {
  1424. client->errorValue = items; /* XXX protocol change */
  1425. return BadValue;
  1426. }
  1427. pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
  1428. /* all the memory for the entire await list is allocated
  1429. * here in one chunk
  1430. */
  1431. pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion));
  1432. if (!pAwaitUnion)
  1433. return BadAlloc;
  1434. /* first item is the header, remainder are real wait conditions */
  1435. pAwaitUnion->header.delete_id = FakeClientID(client->index);
  1436. if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
  1437. {
  1438. xfree(pAwaitUnion);
  1439. return BadAlloc;
  1440. }
  1441. /* don't need to do any more memory allocation for this request! */
  1442. pAwaitUnion->header.client = client;
  1443. pAwaitUnion->header.num_waitconditions = 0;
  1444. pAwait = &(pAwaitUnion+1)->await; /* skip over header */
  1445. for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
  1446. {
  1447. if (pProtocolWaitConds->counter == None) /* XXX protocol change */
  1448. {
  1449. /* this should take care of removing any triggers created by
  1450. * this request that have already been registered on counters
  1451. */
  1452. FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
  1453. client->errorValue = pProtocolWaitConds->counter;
  1454. return SyncErrorBase + XSyncBadCounter;
  1455. }
  1456. /* sanity checks are in SyncInitTrigger */
  1457. pAwait->trigger.pCounter = NULL;
  1458. pAwait->trigger.value_type = pProtocolWaitConds->value_type;
  1459. XSyncIntsToValue(&pAwait->trigger.wait_value,
  1460. pProtocolWaitConds->wait_value_lo,
  1461. pProtocolWaitConds->wait_value_hi);
  1462. pAwait->trigger.test_type = pProtocolWaitConds->test_type;
  1463. status = SyncInitTrigger(client, &pAwait->trigger,
  1464. pProtocolWaitConds->counter, XSyncCAAllTrigger);
  1465. if (status != Success)
  1466. {
  1467. /* this should take care of removing any triggers created by
  1468. * this request that have already been registered on counters
  1469. */
  1470. FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
  1471. return status;
  1472. }
  1473. /* this is not a mistake -- same function works for both cases */
  1474. pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
  1475. pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
  1476. XSyncIntsToValue(&pAwait->event_threshold,
  1477. pProtocolWaitConds->event_threshold_lo,
  1478. pProtocolWaitConds->event_threshold_hi);
  1479. pAwait->pHeader = &pAwaitUnion->header;
  1480. pAwaitUnion->header.num_waitconditions++;
  1481. }
  1482. IgnoreClient(client);
  1483. /* see if any of the triggers are already true */
  1484. pAwait = &(pAwaitUnion+1)->await; /* skip over header */
  1485. for (i = 0; i < items; i++, pAwait++)
  1486. {
  1487. /* don't have to worry about NULL counters because the request
  1488. * errors before we get here out if they occur
  1489. */
  1490. if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger,
  1491. pAwait->trigger.pCounter->value))
  1492. {
  1493. (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
  1494. break; /* once is enough */
  1495. }
  1496. }
  1497. return Success;
  1498. }
  1499. /*
  1500. * ** Query a counter
  1501. */
  1502. static int
  1503. ProcSyncQueryCounter(client)
  1504. ClientPtr client;
  1505. {
  1506. REQUEST(xSyncQueryCounterReq);
  1507. xSyncQueryCounterReply rep;
  1508. SyncCounter *pCounter;
  1509. REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
  1510. pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
  1511. RTCounter, SecurityReadAccess);
  1512. if (pCounter == NULL)
  1513. {
  1514. client->errorValue = stuff->counter;
  1515. return SyncErrorBase + XSyncBadCounter;
  1516. }
  1517. rep.type = X_Reply;
  1518. rep.length = 0;
  1519. rep.sequenceNumber = client->sequence;
  1520. /* if system counter, ask it what the current value is */
  1521. if (IsSystemCounter(pCounter))
  1522. {
  1523. (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
  1524. &pCounter->value);
  1525. }
  1526. rep.value_hi = XSyncValueHigh32(pCounter->value);
  1527. rep.value_lo = XSyncValueLow32(pCounter->value);
  1528. if (client->swapped)
  1529. {
  1530. register char n;
  1531. swaps(&rep.sequenceNumber, n);
  1532. swapl(&rep.length, n);
  1533. swapl(&rep.value_hi, n);
  1534. swapl(&rep.value_lo, n);
  1535. }
  1536. WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
  1537. return (client->noClientException);
  1538. }
  1539. /*
  1540. * ** Create Alarm
  1541. */
  1542. static int
  1543. ProcSyncCreateAlarm(client)
  1544. ClientPtr client;
  1545. {
  1546. REQUEST(xSyncCreateAlarmReq);
  1547. SyncAlarm *pAlarm;
  1548. int status;
  1549. unsigned long len, vmask;
  1550. SyncTrigger *pTrigger;
  1551. REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
  1552. LEGAL_NEW_RESOURCE(stuff->id, client);
  1553. vmask = stuff->valueMask;
  1554. len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2);
  1555. /* the "extra" call to Ones accounts for the presence of 64 bit values */
  1556. if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
  1557. return BadLength;
  1558. if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm))))
  1559. {
  1560. return BadAlloc;
  1561. }
  1562. /* set up defaults */
  1563. pTrigger = &pAlarm->trigger;
  1564. pTrigger->pCounter = NULL;
  1565. pTrigger->value_type = XSyncAbsolute;
  1566. XSyncIntToValue(&pTrigger->wait_value, 0L);
  1567. pTrigger->test_type = XSyncPositiveComparison;
  1568. pTrigger->TriggerFired = SyncAlarmTriggerFired;
  1569. pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
  1570. status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger);
  1571. if (status != Success)
  1572. {
  1573. xfree(pAlarm);
  1574. return status;
  1575. }
  1576. pAlarm->client = client;
  1577. pAlarm->alarm_id = stuff->id;
  1578. XSyncIntToValue(&pAlarm->delta, 1L);
  1579. pAlarm->events = TRUE;
  1580. pAlarm->state = XSyncAlarmInactive;
  1581. pAlarm->pEventClients = NULL;
  1582. status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
  1583. (CARD32 *)&stuff[1]);
  1584. if (status != Success)
  1585. {
  1586. xfree(pAlarm);
  1587. return status;
  1588. }
  1589. if (!AddResource(stuff->id, RTAlarm, pAlarm))
  1590. {
  1591. xfree(pAlarm);
  1592. return BadAlloc;
  1593. }
  1594. /* see if alarm already triggered. NULL counter will not trigger
  1595. * in CreateAlarm and sets alarm state to Inactive.
  1596. */
  1597. if (!pTrigger->pCounter)
  1598. {
  1599. pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
  1600. }
  1601. else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value))
  1602. {
  1603. (*pTrigger->TriggerFired)(pTrigger);
  1604. }
  1605. return Success;
  1606. }
  1607. /*
  1608. * ** Change Alarm
  1609. */
  1610. static int
  1611. ProcSyncChangeAlarm(client)
  1612. ClientPtr client;
  1613. {
  1614. REQUEST(xSyncChangeAlarmReq);
  1615. SyncAlarm *pAlarm;
  1616. long vmask;
  1617. int len, status;
  1618. REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
  1619. if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
  1620. RTAlarm, SecurityWriteAccess)))
  1621. {
  1622. client->errorValue = stuff->alarm;
  1623. return SyncErrorBase + XSyncBadAlarm;
  1624. }
  1625. vmask = stuff->valueMask;
  1626. len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2);
  1627. /* the "extra" call to Ones accounts for the presence of 64 bit values */
  1628. if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
  1629. return BadLength;
  1630. if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
  1631. (CARD32 *)&stuff[1])) != Success)
  1632. return status;
  1633. /* see if alarm already triggered. NULL counter WILL trigger
  1634. * in ChangeAlarm.
  1635. */
  1636. if (!pAlarm->trigger.pCounter ||
  1637. (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger,
  1638. pAlarm->trigger.pCounter->value))
  1639. {
  1640. (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
  1641. }
  1642. return Success;
  1643. }
  1644. static int
  1645. ProcSyncQueryAlarm(client)
  1646. ClientPtr client;
  1647. {
  1648. REQUEST(xS

Large files files are truncated, but you can click here to view the full file