~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to Xext/sync.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Xorg: sync.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
 
2
/*
 
3
 
 
4
Copyright 1991, 1993, 1998  The Open Group
 
5
 
 
6
Permission to use, copy, modify, distribute, and sell this software and its
 
7
documentation for any purpose is hereby granted without fee, provided that
 
8
the above copyright notice appear in all copies and that both that
 
9
copyright notice and this permission notice appear in supporting
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included
 
13
in all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
18
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
21
OTHER DEALINGS IN THE SOFTWARE.
 
22
 
 
23
Except as contained in this notice, the name of The Open Group shall
 
24
not be used in advertising or otherwise to promote the sale, use or
 
25
other dealings in this Software without prior written authorization
 
26
from The Open Group.
 
27
 
 
28
 
 
29
Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
 
30
and Olivetti Research Limited, Cambridge, England.
 
31
 
 
32
                        All Rights Reserved
 
33
 
 
34
Permission to use, copy, modify, and distribute this software and its
 
35
documentation for any purpose and without fee is hereby granted,
 
36
provided that the above copyright notice appear in all copies and that
 
37
both that copyright notice and this permission notice appear in
 
38
supporting documentation, and that the names of Digital or Olivetti 
 
39
not be used in advertising or publicity pertaining to distribution of the
 
40
software without specific, written prior permission.  Digital and Olivetti
 
41
make no representations about the suitability of this software
 
42
for any purpose.  It is provided "as is" without express or implied warranty.
 
43
 
 
44
DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 
45
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 
46
FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
47
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
 
48
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 
49
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
50
PERFORMANCE OF THIS SOFTWARE.
 
51
 
 
52
*/
 
53
/* $XFree86: xc/programs/Xserver/Xext/sync.c,v 3.13 2003/09/02 18:19:01 tsi Exp $ */
 
54
 
 
55
#define NEED_REPLIES
 
56
#define NEED_EVENTS
 
57
#ifdef HAVE_DIX_CONFIG_H
 
58
#include <dix-config.h>
 
59
#endif
 
60
 
 
61
#include <X11/X.h>
 
62
#include <X11/Xproto.h>
 
63
#include <X11/Xmd.h>
 
64
#include "misc.h"
 
65
#include "os.h"
 
66
#include "extnsionst.h"
 
67
#include "dixstruct.h"
 
68
#include "resource.h"
 
69
#include "opaque.h"
 
70
#define _SYNC_SERVER
 
71
#include <X11/extensions/sync.h>
 
72
#include <X11/extensions/syncstr.h>
 
73
 
 
74
#ifdef EXTMODULE
 
75
#include "xf86_ansic.h"
 
76
#else
 
77
#include <stdio.h>
 
78
#if !defined(WIN32) && !defined(Lynx)
 
79
#include <sys/time.h>
 
80
#endif
 
81
#endif
 
82
 
 
83
#include "modinit.h"
 
84
 
 
85
/*
 
86
 * Local Global Variables
 
87
 */
 
88
static int      SyncEventBase;
 
89
static int      SyncErrorBase;
 
90
static RESTYPE  RTCounter = 0;
 
91
static RESTYPE  RTAwait;
 
92
static RESTYPE  RTAlarm;
 
93
static RESTYPE  RTAlarmClient;
 
94
static int SyncNumSystemCounters = 0;
 
95
static SyncCounter **SysCounterList = NULL;
 
96
 
 
97
#define IsSystemCounter(pCounter) \
 
98
    (pCounter && (pCounter->client == NULL))
 
99
 
 
100
/* these are all the alarm attributes that pertain to the alarm's trigger */
 
101
#define XSyncCAAllTrigger \
 
102
    (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
 
103
 
 
104
static int
 
105
FreeAlarm(
 
106
    pointer /* addr */,
 
107
    XID /* id */
 
108
);
 
109
 
 
110
static int
 
111
FreeAlarmClient(
 
112
    pointer /* value */,
 
113
    XID /* id */
 
114
);
 
115
 
 
116
static int
 
117
FreeAwait(
 
118
    pointer /* addr */,
 
119
    XID /* id */
 
120
);
 
121
 
 
122
static void
 
123
ServertimeBracketValues(
 
124
    pointer /* pCounter */,
 
125
    CARD64 * /* pbracket_less */,
 
126
    CARD64 * /* pbracket_greater */
 
127
);
 
128
 
 
129
static void
 
130
ServertimeQueryValue(
 
131
    pointer /* pCounter */,
 
132
    CARD64 * /* pValue_return */
 
133
);
 
134
 
 
135
static void
 
136
ServertimeWakeupHandler(
 
137
    pointer /* env */,
 
138
    int /* rc */,
 
139
    pointer /* LastSelectMask */
 
140
);
 
141
 
 
142
static int 
 
143
SyncInitTrigger(
 
144
    ClientPtr /* client */,
 
145
    SyncTrigger * /* pTrigger */,
 
146
    XSyncCounter /* counter */,
 
147
    Mask /* changes */
 
148
);
 
149
 
 
150
static void
 
151
SAlarmNotifyEvent(
 
152
    xSyncAlarmNotifyEvent * /* from */,
 
153
    xSyncAlarmNotifyEvent * /* to */
 
154
);
 
155
 
 
156
static void
 
157
SCounterNotifyEvent(
 
158
    xSyncCounterNotifyEvent * /* from */,
 
159
    xSyncCounterNotifyEvent * /* to */
 
160
);
 
161
 
 
162
static void
 
163
ServertimeBlockHandler(
 
164
    pointer  /* env */,
 
165
    struct timeval ** /* wt */,
 
166
    pointer  /* LastSelectMask */
 
167
);
 
168
 
 
169
static int
 
170
SyncAddTriggerToCounter(
 
171
    SyncTrigger * /* pTrigger */
 
172
);
 
173
 
 
174
extern void
 
175
SyncAlarmCounterDestroyed(
 
176
    SyncTrigger * /* pTrigger */
 
177
);
 
178
 
 
179
static void
 
180
SyncAlarmTriggerFired(
 
181
    SyncTrigger * /* pTrigger */
 
182
);
 
183
 
 
184
static void
 
185
SyncAwaitTriggerFired(
 
186
    SyncTrigger * /* pTrigger */
 
187
);
 
188
 
 
189
static int
 
190
SyncChangeAlarmAttributes(
 
191
    ClientPtr /* client */,
 
192
    SyncAlarm * /* pAlarm */,
 
193
    Mask /* mask */,
 
194
    CARD32 * /* values */
 
195
);
 
196
 
 
197
static Bool
 
198
SyncCheckTriggerNegativeComparison(
 
199
    SyncTrigger * /* pTrigger */,
 
200
    CARD64 /* oldval */
 
201
);
 
202
 
 
203
static Bool
 
204
SyncCheckTriggerNegativeTransition(
 
205
    SyncTrigger * /* pTrigger */,
 
206
    CARD64 /* oldval */
 
207
);
 
208
 
 
209
static Bool
 
210
SyncCheckTriggerPositiveComparison(
 
211
    SyncTrigger * /* pTrigger */,
 
212
    CARD64 /* oldval */
 
213
);
 
214
 
 
215
static Bool
 
216
SyncCheckTriggerPositiveTransition(
 
217
    SyncTrigger * /* pTrigger */,
 
218
    CARD64 /* oldval */
 
219
);
 
220
 
 
221
static SyncCounter *
 
222
SyncCreateCounter(
 
223
    ClientPtr /* client */,
 
224
    XSyncCounter /* id */,
 
225
    CARD64 /* initialvalue */
 
226
);
 
227
 
 
228
static void SyncComputeBracketValues(
 
229
    SyncCounter * /* pCounter */,
 
230
    Bool /* startOver */
 
231
);
 
232
 
 
233
static void
 
234
SyncDeleteTriggerFromCounter(
 
235
    SyncTrigger * /* pTrigger */
 
236
);
 
237
 
 
238
static Bool
 
239
SyncEventSelectForAlarm(
 
240
    SyncAlarm * /* pAlarm */,
 
241
    ClientPtr /* client */,
 
242
    Bool /* wantevents */
 
243
);
 
244
 
 
245
static void
 
246
SyncInitServerTime(
 
247
    void
 
248
);
 
249
 
 
250
static void 
 
251
SyncResetProc(
 
252
    ExtensionEntry * /* extEntry */
 
253
);
 
254
 
 
255
static void
 
256
SyncSendAlarmNotifyEvents(
 
257
    SyncAlarm * /* pAlarm */
 
258
);
 
259
 
 
260
static void
 
261
SyncSendCounterNotifyEvents(
 
262
    ClientPtr /* client */,
 
263
    SyncAwait ** /* ppAwait */,
 
264
    int /* num_events */
 
265
);
 
266
 
 
267
static DISPATCH_PROC(ProcSyncAwait);
 
268
static DISPATCH_PROC(ProcSyncChangeAlarm);
 
269
static DISPATCH_PROC(ProcSyncChangeCounter);
 
270
static DISPATCH_PROC(ProcSyncCreateAlarm);
 
271
static DISPATCH_PROC(ProcSyncCreateCounter);
 
272
static DISPATCH_PROC(ProcSyncDestroyAlarm);
 
273
static DISPATCH_PROC(ProcSyncDestroyCounter);
 
274
static DISPATCH_PROC(ProcSyncDispatch);
 
275
static DISPATCH_PROC(ProcSyncGetPriority);
 
276
static DISPATCH_PROC(ProcSyncInitialize);
 
277
static DISPATCH_PROC(ProcSyncListSystemCounters);
 
278
static DISPATCH_PROC(ProcSyncQueryAlarm);
 
279
static DISPATCH_PROC(ProcSyncQueryCounter);
 
280
static DISPATCH_PROC(ProcSyncSetCounter);
 
281
static DISPATCH_PROC(ProcSyncSetPriority);
 
282
static DISPATCH_PROC(SProcSyncAwait);
 
283
static DISPATCH_PROC(SProcSyncChangeAlarm);
 
284
static DISPATCH_PROC(SProcSyncChangeCounter);
 
285
static DISPATCH_PROC(SProcSyncCreateAlarm);
 
286
static DISPATCH_PROC(SProcSyncCreateCounter);
 
287
static DISPATCH_PROC(SProcSyncDestroyAlarm);
 
288
static DISPATCH_PROC(SProcSyncDestroyCounter);
 
289
static DISPATCH_PROC(SProcSyncDispatch);
 
290
static DISPATCH_PROC(SProcSyncGetPriority);
 
291
static DISPATCH_PROC(SProcSyncInitialize);
 
292
static DISPATCH_PROC(SProcSyncListSystemCounters);
 
293
static DISPATCH_PROC(SProcSyncQueryAlarm);
 
294
static DISPATCH_PROC(SProcSyncQueryCounter);
 
295
static DISPATCH_PROC(SProcSyncSetCounter);
 
296
static DISPATCH_PROC(SProcSyncSetPriority);
 
297
 
 
298
/*  Each counter maintains a simple linked list of triggers that are
 
299
 *  interested in the counter.  The two functions below are used to
 
300
 *  delete and add triggers on this list.
 
301
 */
 
302
static void
 
303
SyncDeleteTriggerFromCounter(pTrigger)
 
304
    SyncTrigger *pTrigger;
 
305
{
 
306
    SyncTriggerList *pCur, *pPrev = NULL;
 
307
 
 
308
    /* pCounter needs to be stored in pTrigger before calling here. */
 
309
 
 
310
    if (!pTrigger->pCounter)
 
311
        return;
 
312
 
 
313
    for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
 
314
    {
 
315
        if (pCur->pTrigger == pTrigger)
 
316
        {
 
317
            if (pPrev)
 
318
                pPrev->next = pCur->next;
 
319
            else
 
320
                pTrigger->pCounter->pTriglist = pCur->next;
 
321
            xfree(pCur);
 
322
            break;
 
323
        }
 
324
    }
 
325
 
 
326
    if (IsSystemCounter(pTrigger->pCounter))
 
327
        SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
 
328
}
 
329
 
 
330
 
 
331
static int
 
332
SyncAddTriggerToCounter(pTrigger)
 
333
    SyncTrigger *pTrigger;
 
334
{
 
335
    SyncTriggerList *pCur;
 
336
 
 
337
    if (!pTrigger->pCounter)
 
338
        return Success;
 
339
 
 
340
    /* don't do anything if it's already there */
 
341
    for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
 
342
    {
 
343
        if (pCur->pTrigger == pTrigger)
 
344
            return Success;
 
345
    }
 
346
 
 
347
    if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList))))
 
348
        return BadAlloc;
 
349
 
 
350
    pCur->pTrigger = pTrigger;
 
351
    pCur->next = pTrigger->pCounter->pTriglist;
 
352
    pTrigger->pCounter->pTriglist = pCur;
 
353
 
 
354
    if (IsSystemCounter(pTrigger->pCounter))
 
355
        SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
 
356
 
 
357
    return Success;
 
358
}
 
359
 
 
360
 
 
361
/*  Below are four possible functions that can be plugged into 
 
362
 *  pTrigger->CheckTrigger, corresponding to the four possible
 
363
 *  test-types.  These functions are called after the counter's
 
364
 *  value changes but are also passed the old counter value
 
365
 *  so they can inspect both the old and new values.
 
366
 *  (PositiveTransition and NegativeTransition need to see both
 
367
 *  pieces of information.)  These functions return the truth value
 
368
 *  of the trigger.
 
369
 *
 
370
 *  All of them include the condition pTrigger->pCounter == NULL.
 
371
 *  This is because the spec says that a trigger with a counter value 
 
372
 *  of None is always TRUE.
 
373
 */
 
374
 
 
375
static Bool
 
376
SyncCheckTriggerPositiveComparison(pTrigger, oldval)
 
377
    SyncTrigger *pTrigger;
 
378
    CARD64      oldval;
 
379
{
 
380
    return (pTrigger->pCounter == NULL ||
 
381
            XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
 
382
                                     pTrigger->test_value));
 
383
}
 
384
 
 
385
static Bool
 
386
SyncCheckTriggerNegativeComparison(pTrigger, oldval)
 
387
    SyncTrigger *pTrigger;
 
388
    CARD64      oldval;
 
389
{
 
390
    return (pTrigger->pCounter == NULL ||
 
391
            XSyncValueLessOrEqual(pTrigger->pCounter->value,
 
392
                                  pTrigger->test_value));
 
393
}
 
394
 
 
395
static Bool
 
396
SyncCheckTriggerPositiveTransition(pTrigger, oldval)
 
397
    SyncTrigger *pTrigger;
 
398
    CARD64      oldval;
 
399
{
 
400
    return (pTrigger->pCounter == NULL ||
 
401
            (XSyncValueLessThan(oldval, pTrigger->test_value) &&
 
402
             XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
 
403
                                      pTrigger->test_value)));
 
404
}
 
405
 
 
406
static Bool
 
407
SyncCheckTriggerNegativeTransition(pTrigger, oldval)
 
408
    SyncTrigger *pTrigger;
 
409
    CARD64      oldval;
 
410
{
 
411
    return (pTrigger->pCounter == NULL ||
 
412
            (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
 
413
             XSyncValueLessOrEqual(pTrigger->pCounter->value,
 
414
                                   pTrigger->test_value)));
 
415
}
 
416
 
 
417
 
 
418
 
 
419
static int 
 
420
SyncInitTrigger(client, pTrigger, counter, changes) 
 
421
    ClientPtr        client;    /* so we can set errorValue */
 
422
    SyncTrigger      *pTrigger;
 
423
    XSyncCounter     counter; 
 
424
    Mask             changes;
 
425
{
 
426
    SyncCounter *pCounter = pTrigger->pCounter;
 
427
    int         status;
 
428
    Bool        newcounter = FALSE;
 
429
 
 
430
    if (changes & XSyncCACounter)
 
431
    {
 
432
        if (counter == None)
 
433
            pCounter = NULL;
 
434
        else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType(
 
435
                        client, counter, RTCounter, SecurityReadAccess)))
 
436
        {
 
437
            client->errorValue = counter;
 
438
            return SyncErrorBase + XSyncBadCounter;
 
439
        }
 
440
        if (pCounter != pTrigger->pCounter)
 
441
        { /* new counter for trigger */
 
442
            SyncDeleteTriggerFromCounter(pTrigger);
 
443
            pTrigger->pCounter = pCounter;
 
444
            newcounter = TRUE;
 
445
        }
 
446
    }
 
447
 
 
448
    /* if system counter, ask it what the current value is */
 
449
 
 
450
    if (IsSystemCounter(pCounter))
 
451
    {
 
452
        (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
 
453
                                                  &pCounter->value);
 
454
    }
 
455
 
 
456
    if (changes & XSyncCAValueType)
 
457
    {
 
458
        if (pTrigger->value_type != XSyncRelative &&
 
459
            pTrigger->value_type != XSyncAbsolute)
 
460
        {
 
461
            client->errorValue = pTrigger->value_type;
 
462
            return BadValue;
 
463
        }
 
464
    }
 
465
 
 
466
    if (changes & XSyncCATestType)
 
467
    {
 
468
        if (pTrigger->test_type != XSyncPositiveTransition &&
 
469
            pTrigger->test_type != XSyncNegativeTransition &&
 
470
            pTrigger->test_type != XSyncPositiveComparison &&
 
471
            pTrigger->test_type != XSyncNegativeComparison)
 
472
        {
 
473
            client->errorValue = pTrigger->test_type;
 
474
            return BadValue;
 
475
        }
 
476
        /* select appropriate CheckTrigger function */
 
477
 
 
478
        switch (pTrigger->test_type)
 
479
        {
 
480
        case XSyncPositiveTransition: 
 
481
            pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
 
482
            break;
 
483
        case XSyncNegativeTransition: 
 
484
            pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
 
485
            break;
 
486
        case XSyncPositiveComparison: 
 
487
            pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
 
488
            break;
 
489
        case XSyncNegativeComparison: 
 
490
            pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
 
491
            break;
 
492
        }
 
493
    }
 
494
 
 
495
    if (changes & (XSyncCAValueType | XSyncCAValue))
 
496
    {
 
497
        if (pTrigger->value_type == XSyncAbsolute)
 
498
            pTrigger->test_value = pTrigger->wait_value;
 
499
        else /* relative */
 
500
        {
 
501
            Bool overflow;
 
502
            if (pCounter == NULL)
 
503
                return BadMatch;
 
504
 
 
505
            XSyncValueAdd(&pTrigger->test_value, pCounter->value, 
 
506
                          pTrigger->wait_value, &overflow);
 
507
            if (overflow)
 
508
            {
 
509
                client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
 
510
                return BadValue;
 
511
            }
 
512
        }
 
513
    }
 
514
 
 
515
    /*  we wait until we're sure there are no errors before registering
 
516
     *  a new counter on a trigger
 
517
     */
 
518
    if (newcounter)
 
519
    {
 
520
        if ((status = SyncAddTriggerToCounter(pTrigger)) != Success)
 
521
            return status;
 
522
    }
 
523
    else if (IsSystemCounter(pCounter))
 
524
    {
 
525
        SyncComputeBracketValues(pCounter, /*startOver*/ TRUE);
 
526
    }
 
527
    
 
528
    return Success;
 
529
}
 
530
 
 
531
/*  AlarmNotify events happen in response to actions taken on an Alarm or
 
532
 *  the counter used by the alarm.  AlarmNotify may be sent to multiple 
 
533
 *  clients.  The alarm maintains a list of clients interested in events.
 
534
 */
 
535
static void
 
536
SyncSendAlarmNotifyEvents(pAlarm)
 
537
    SyncAlarm *pAlarm;
 
538
{
 
539
    SyncAlarmClientList *pcl;
 
540
    xSyncAlarmNotifyEvent ane;
 
541
    SyncTrigger *pTrigger = &pAlarm->trigger;
 
542
 
 
543
    UpdateCurrentTime();
 
544
 
 
545
    ane.type = SyncEventBase + XSyncAlarmNotify;
 
546
    ane.kind = XSyncAlarmNotify;
 
547
    ane.sequenceNumber = pAlarm->client->sequence;
 
548
    ane.alarm = pAlarm->alarm_id;
 
549
    if (pTrigger->pCounter)
 
550
    {
 
551
        ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
 
552
        ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
 
553
    }
 
554
    else
 
555
    { /* XXX what else can we do if there's no counter? */
 
556
        ane.counter_value_hi = ane.counter_value_lo = 0;
 
557
    }
 
558
 
 
559
    ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value);
 
560
    ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value);
 
561
    ane.time = currentTime.milliseconds;
 
562
    ane.state = pAlarm->state;
 
563
 
 
564
    /* send to owner */
 
565
    if (pAlarm->events && !pAlarm->client->clientGone) 
 
566
        WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
 
567
 
 
568
    /* send to other interested clients */
 
569
    for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
 
570
    {
 
571
        if (!pAlarm->client->clientGone)
 
572
        {
 
573
            ane.sequenceNumber = pcl->client->sequence;
 
574
            WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
 
575
        }
 
576
    }
 
577
}
 
578
 
 
579
 
 
580
/*  CounterNotify events only occur in response to an Await.  The events 
 
581
 *  go only to the Awaiting client.
 
582
 */
 
583
static void
 
584
SyncSendCounterNotifyEvents(client, ppAwait, num_events)
 
585
    ClientPtr client;
 
586
    SyncAwait **ppAwait;
 
587
    int num_events;
 
588
{
 
589
    xSyncCounterNotifyEvent *pEvents, *pev;
 
590
    int i;
 
591
 
 
592
    if (client->clientGone)
 
593
        return;
 
594
    pev = pEvents = (xSyncCounterNotifyEvent *)
 
595
                 ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent));
 
596
    if (!pEvents) 
 
597
        return;
 
598
    UpdateCurrentTime();
 
599
    for (i = 0; i < num_events; i++, ppAwait++, pev++)
 
600
    {
 
601
        SyncTrigger *pTrigger = &(*ppAwait)->trigger;
 
602
        pev->type = SyncEventBase + XSyncCounterNotify;
 
603
        pev->kind = XSyncCounterNotify;
 
604
        pev->sequenceNumber = client->sequence;
 
605
        pev->counter = pTrigger->pCounter->id;
 
606
        pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
 
607
        pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
 
608
        pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
 
609
        pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
 
610
        pev->time = currentTime.milliseconds;
 
611
        pev->count = num_events - i - 1; /* events remaining */
 
612
        pev->destroyed = pTrigger->pCounter->beingDestroyed;
 
613
    }
 
614
    /* swapping will be taken care of by this */
 
615
    WriteEventsToClient(client, num_events, (xEvent *)pEvents);
 
616
    DEALLOCATE_LOCAL(pEvents);
 
617
}
 
618
 
 
619
 
 
620
/* This function is called when an alarm's counter is destroyed.
 
621
 * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
 
622
 */
 
623
void
 
624
SyncAlarmCounterDestroyed(pTrigger)
 
625
    SyncTrigger *pTrigger;
 
626
{
 
627
    SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
 
628
 
 
629
    pAlarm->state = XSyncAlarmInactive;
 
630
    SyncSendAlarmNotifyEvents(pAlarm);
 
631
    pTrigger->pCounter = NULL;
 
632
}
 
633
 
 
634
 
 
635
/*  This function is called when an alarm "goes off."  
 
636
 *  It is plugged into pTrigger->TriggerFired (for alarm triggers).
 
637
 */
 
638
static void
 
639
SyncAlarmTriggerFired(pTrigger)
 
640
    SyncTrigger *pTrigger;
 
641
{
 
642
    SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
 
643
    CARD64 new_test_value;
 
644
 
 
645
    /* no need to check alarm unless it's active */
 
646
    if (pAlarm->state != XSyncAlarmActive)
 
647
        return;
 
648
 
 
649
    /*  " if the counter value is None, or if the delta is 0 and
 
650
     *    the test-type is PositiveComparison or NegativeComparison,
 
651
     *    no change is made to value (test-value) and the alarm
 
652
     *    state is changed to Inactive before the event is generated."
 
653
     */
 
654
    if (pAlarm->trigger.pCounter == NULL
 
655
        || (XSyncValueIsZero(pAlarm->delta)
 
656
            && (pAlarm->trigger.test_type == XSyncPositiveComparison
 
657
                || pAlarm->trigger.test_type == XSyncNegativeComparison)))
 
658
        pAlarm->state = XSyncAlarmInactive;
 
659
 
 
660
    new_test_value = pAlarm->trigger.test_value;
 
661
 
 
662
    if (pAlarm->state == XSyncAlarmActive)
 
663
    {
 
664
        Bool overflow;
 
665
        CARD64 oldvalue;
 
666
        SyncTrigger *paTrigger = &pAlarm->trigger;
 
667
 
 
668
        /* "The alarm is updated by repeatedly adding delta to the
 
669
         *  value of the trigger and re-initializing it until it
 
670
         *  becomes FALSE."
 
671
         */
 
672
        oldvalue = paTrigger->test_value;
 
673
 
 
674
        /* XXX really should do something smarter here */
 
675
 
 
676
        do
 
677
        {
 
678
            XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
 
679
                          pAlarm->delta, &overflow);
 
680
        } while (!overflow && 
 
681
              (*paTrigger->CheckTrigger)(paTrigger,
 
682
                                        paTrigger->pCounter->value));
 
683
 
 
684
        new_test_value = paTrigger->test_value;
 
685
        paTrigger->test_value = oldvalue;
 
686
 
 
687
        /* "If this update would cause value to fall outside the range
 
688
         *  for an INT64...no change is made to value (test-value) and
 
689
         *  the alarm state is changed to Inactive before the event is
 
690
         *  generated."
 
691
         */
 
692
        if (overflow)
 
693
        {
 
694
            new_test_value = oldvalue;
 
695
            pAlarm->state = XSyncAlarmInactive;
 
696
        }
 
697
    }
 
698
    /*  The AlarmNotify event has to have the "new state of the alarm"
 
699
     *  which we can't be sure of until this point.  However, it has
 
700
     *  to have the "old" trigger test value.  That's the reason for
 
701
     *  all the newvalue/oldvalue shuffling above.  After we send the
 
702
     *  events, give the trigger its new test value.
 
703
     */
 
704
    SyncSendAlarmNotifyEvents(pAlarm);
 
705
    pTrigger->test_value = new_test_value;
 
706
}
 
707
 
 
708
 
 
709
/*  This function is called when an Await unblocks, either as a result
 
710
 *  of the trigger firing OR the counter being destroyed.
 
711
 *  It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
 
712
 *  (for Await triggers).
 
713
 */
 
714
static void
 
715
SyncAwaitTriggerFired(pTrigger)
 
716
    SyncTrigger *pTrigger;
 
717
{
 
718
    SyncAwait *pAwait = (SyncAwait *)pTrigger;
 
719
    int numwaits;
 
720
    SyncAwaitUnion *pAwaitUnion;
 
721
    SyncAwait **ppAwait;
 
722
    int num_events = 0;
 
723
 
 
724
    pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
 
725
    numwaits = pAwaitUnion->header.num_waitconditions;
 
726
    ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *));
 
727
    if (!ppAwait)
 
728
        goto bail;
 
729
 
 
730
    pAwait = &(pAwaitUnion+1)->await;
 
731
 
 
732
    /* "When a client is unblocked, all the CounterNotify events for
 
733
     *  the Await request are generated contiguously. If count is 0
 
734
     *  there are no more events to follow for this request. If
 
735
     *  count is n, there are at least n more events to follow."
 
736
     *
 
737
     *  Thus, it is best to find all the counters for which events
 
738
     *  need to be sent first, so that an accurate count field can
 
739
     *  be stored in the events.
 
740
     */
 
741
    for ( ; numwaits; numwaits--, pAwait++)
 
742
    {
 
743
        CARD64 diff;
 
744
        Bool overflow, diffgreater, diffequal;
 
745
 
 
746
        /* "A CounterNotify event with the destroyed flag set to TRUE is
 
747
         *  always generated if the counter for one of the triggers is
 
748
         *  destroyed."
 
749
         */
 
750
        if (pAwait->trigger.pCounter->beingDestroyed)
 
751
        {
 
752
            ppAwait[num_events++] = pAwait;
 
753
            continue;
 
754
        }
 
755
 
 
756
        /* "The difference between the counter and the test value is
 
757
         *  calculated by subtracting the test value from the value of
 
758
         *  the counter."
 
759
         */
 
760
        XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value,
 
761
                           pAwait->trigger.test_value, &overflow);
 
762
 
 
763
        /* "If the difference lies outside the range for an INT64, an
 
764
         *  event is not generated."
 
765
         */
 
766
        if (overflow)
 
767
            continue;
 
768
        diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
 
769
        diffequal   = XSyncValueEqual(diff, pAwait->event_threshold);
 
770
 
 
771
        /* "If the test-type is PositiveTransition or
 
772
         *  PositiveComparison, a CounterNotify event is generated if
 
773
         *  the difference is at least event-threshold. If the test-type
 
774
         *  is NegativeTransition or NegativeComparison, a CounterNotify
 
775
         *  event is generated if the difference is at most
 
776
         *  event-threshold."
 
777
         */
 
778
 
 
779
        if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
 
780
               pAwait->trigger.test_type == XSyncPositiveTransition)
 
781
               && (diffgreater || diffequal))
 
782
             ||
 
783
             ((pAwait->trigger.test_type == XSyncNegativeComparison ||
 
784
               pAwait->trigger.test_type == XSyncNegativeTransition)
 
785
              && (!diffgreater) /* less or equal */
 
786
              )
 
787
           )
 
788
        {
 
789
            ppAwait[num_events++] = pAwait;
 
790
        }
 
791
    }
 
792
    if (num_events)
 
793
        SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
 
794
                                    num_events);
 
795
    DEALLOCATE_LOCAL(ppAwait);
 
796
 
 
797
bail:
 
798
    /* unblock the client */
 
799
    AttendClient(pAwaitUnion->header.client);
 
800
    /* delete the await */
 
801
    FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
 
802
}
 
803
 
 
804
 
 
805
/*  This function should always be used to change a counter's value so that
 
806
 *  any triggers depending on the counter will be checked.
 
807
 */
 
808
void
 
809
SyncChangeCounter(pCounter, newval)
 
810
    SyncCounter    *pCounter;
 
811
    CARD64         newval;
 
812
{
 
813
    SyncTriggerList       *ptl, *pnext;
 
814
    CARD64 oldval;
 
815
 
 
816
    oldval = pCounter->value;
 
817
    pCounter->value = newval;
 
818
 
 
819
    /* run through triggers to see if any become true */
 
820
    for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
 
821
    {
 
822
        pnext = ptl->next;
 
823
        if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
 
824
            (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
 
825
    }
 
826
 
 
827
    if (IsSystemCounter(pCounter))
 
828
    {
 
829
        SyncComputeBracketValues(pCounter, /* startOver */ FALSE);
 
830
    }
 
831
}
 
832
 
 
833
 
 
834
/* loosely based on dix/events.c/EventSelectForWindow */
 
835
static Bool
 
836
SyncEventSelectForAlarm(pAlarm, client, wantevents)
 
837
    SyncAlarm *pAlarm;
 
838
    ClientPtr client;
 
839
    Bool      wantevents;
 
840
{
 
841
    SyncAlarmClientList *pClients;
 
842
 
 
843
    if (client == pAlarm->client) /* alarm owner */
 
844
    {
 
845
        pAlarm->events = wantevents;
 
846
        return Success;
 
847
    }
 
848
 
 
849
    /* see if the client is already on the list (has events selected) */
 
850
 
 
851
    for (pClients = pAlarm->pEventClients; pClients;
 
852
         pClients = pClients->next)
 
853
    {
 
854
        if (pClients->client == client)
 
855
        {
 
856
            /* client's presence on the list indicates desire for 
 
857
             * events.  If the client doesn't want events, remove it 
 
858
             * from the list.  If the client does want events, do
 
859
             * nothing, since it's already got them.
 
860
             */
 
861
            if (!wantevents)
 
862
            {
 
863
                FreeResource(pClients->delete_id, RT_NONE);
 
864
            }
 
865
            return Success;
 
866
        }
 
867
    }
 
868
 
 
869
    /*  if we get here, this client does not currently have
 
870
     *  events selected on the alarm
 
871
     */
 
872
 
 
873
    if (!wantevents)
 
874
        /* client doesn't want events, and we just discovered that it 
 
875
         * doesn't have them, so there's nothing to do.
 
876
         */
 
877
        return Success;
 
878
 
 
879
    /* add new client to pAlarm->pEventClients */
 
880
 
 
881
    pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList));
 
882
    if (!pClients)
 
883
        return BadAlloc;
 
884
 
 
885
    /*  register it as a resource so it will be cleaned up 
 
886
     *  if the client dies
 
887
     */
 
888
 
 
889
    pClients->delete_id = FakeClientID(client->index);
 
890
    if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
 
891
    {
 
892
        xfree(pClients);
 
893
        return BadAlloc;
 
894
    }
 
895
 
 
896
    /* link it into list after we know all the allocations succeed */
 
897
 
 
898
    pClients->next = pAlarm->pEventClients;
 
899
    pAlarm->pEventClients = pClients;
 
900
    pClients->client = client;
 
901
    return Success;
 
902
}
 
903
 
 
904
/*
 
905
 * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
 
906
 */
 
907
static int 
 
908
SyncChangeAlarmAttributes(client, pAlarm, mask, values)
 
909
    ClientPtr       client;
 
910
    SyncAlarm      *pAlarm;
 
911
    Mask            mask;
 
912
    CARD32          *values;
 
913
{
 
914
    int            status;
 
915
    XSyncCounter   counter;
 
916
    Mask           origmask = mask;
 
917
 
 
918
    counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None;
 
919
 
 
920
    while (mask)
 
921
    {
 
922
        int    index2 = lowbit(mask);
 
923
        mask &= ~index2;
 
924
        switch (index2)
 
925
        {
 
926
          case XSyncCACounter:
 
927
            mask &= ~XSyncCACounter;
 
928
            /* sanity check in SyncInitTrigger */
 
929
            counter = *values++;
 
930
            break;
 
931
 
 
932
          case XSyncCAValueType:
 
933
            mask &= ~XSyncCAValueType;
 
934
            /* sanity check in SyncInitTrigger */
 
935
            pAlarm->trigger.value_type = *values++;
 
936
            break;
 
937
 
 
938
          case XSyncCAValue:
 
939
            mask &= ~XSyncCAValue;
 
940
            XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
 
941
            values += 2;
 
942
            break;
 
943
 
 
944
          case XSyncCATestType:
 
945
            mask &= ~XSyncCATestType;
 
946
            /* sanity check in SyncInitTrigger */
 
947
            pAlarm->trigger.test_type = *values++;
 
948
            break;
 
949
 
 
950
          case XSyncCADelta:
 
951
            mask &= ~XSyncCADelta;
 
952
            XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
 
953
            values += 2;
 
954
            break;
 
955
 
 
956
          case XSyncCAEvents:
 
957
            mask &= ~XSyncCAEvents;
 
958
            if ((*values != xTrue) && (*values != xFalse))
 
959
            {
 
960
                client->errorValue = *values;
 
961
                return BadValue;
 
962
            }
 
963
            status = SyncEventSelectForAlarm(pAlarm, client,
 
964
                                             (Bool)(*values++));
 
965
            if (status != Success)
 
966
                return status;
 
967
            break;
 
968
 
 
969
          default:
 
970
            client->errorValue = mask;
 
971
            return BadValue;
 
972
        }
 
973
    }
 
974
 
 
975
    /* "If the test-type is PositiveComparison or PositiveTransition
 
976
     *  and delta is less than zero, or if the test-type is
 
977
     *  NegativeComparison or NegativeTransition and delta is
 
978
     *  greater than zero, a Match error is generated."
 
979
     */
 
980
    if (origmask & (XSyncCADelta|XSyncCATestType))
 
981
    {
 
982
        CARD64 zero;
 
983
        XSyncIntToValue(&zero, 0);
 
984
        if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
 
985
              (pAlarm->trigger.test_type == XSyncPositiveTransition))
 
986
             && XSyncValueLessThan(pAlarm->delta, zero))
 
987
            ||
 
988
            (((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
 
989
              (pAlarm->trigger.test_type == XSyncNegativeTransition))
 
990
             && XSyncValueGreaterThan(pAlarm->delta, zero))
 
991
           )
 
992
        {
 
993
            return BadMatch;
 
994
        }
 
995
    }
 
996
 
 
997
    /* postpone this until now, when we're sure nothing else can go wrong */
 
998
    if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter,
 
999
                             origmask & XSyncCAAllTrigger)) != Success)
 
1000
        return status;
 
1001
 
 
1002
    /* XXX spec does not really say to do this - needs clarification */
 
1003
    pAlarm->state = XSyncAlarmActive;
 
1004
    return Success;
 
1005
}
 
1006
 
 
1007
 
 
1008
static SyncCounter *
 
1009
SyncCreateCounter(client, id, initialvalue)
 
1010
    ClientPtr   client;
 
1011
    XSyncCounter id;
 
1012
    CARD64      initialvalue;
 
1013
{
 
1014
    SyncCounter *pCounter;
 
1015
 
 
1016
    if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter))))
 
1017
        return (SyncCounter *)NULL;
 
1018
 
 
1019
    if (!AddResource(id, RTCounter, (pointer) pCounter))
 
1020
    {
 
1021
        xfree((pointer) pCounter);
 
1022
        return (SyncCounter *)NULL;
 
1023
    }
 
1024
 
 
1025
    pCounter->client = client;
 
1026
    pCounter->id = id;
 
1027
    pCounter->value = initialvalue;
 
1028
    pCounter->pTriglist = NULL;
 
1029
    pCounter->beingDestroyed = FALSE;
 
1030
    pCounter->pSysCounterInfo = NULL;
 
1031
    return pCounter;
 
1032
}
 
1033
 
 
1034
static int FreeCounter(
 
1035
    pointer /*env*/,
 
1036
    XID     /*id*/
 
1037
);
 
1038
 
 
1039
/*
 
1040
 * ***** System Counter utilities
 
1041
 */
 
1042
 
 
1043
pointer 
 
1044
SyncCreateSystemCounter(name, initial, resolution, counterType,
 
1045
                        QueryValue, BracketValues)
 
1046
    char           *name;
 
1047
    CARD64          initial;
 
1048
    CARD64          resolution;
 
1049
    SyncCounterType counterType;
 
1050
    void            (*QueryValue) (
 
1051
        pointer /* pCounter */, 
 
1052
        CARD64 * /* pValue_return */);
 
1053
    void            (*BracketValues) (
 
1054
        pointer /* pCounter */,
 
1055
        CARD64 * /* pbracket_less */,
 
1056
        CARD64 * /* pbracket_greater */);
 
1057
{
 
1058
    SyncCounter    *pCounter;
 
1059
 
 
1060
    SysCounterList = (SyncCounter **)xrealloc(SysCounterList,
 
1061
                            (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
 
1062
    if (!SysCounterList)
 
1063
        return (pointer)NULL;
 
1064
 
 
1065
    /* this function may be called before SYNC has been initialized, so we
 
1066
     * have to make sure RTCounter is created.
 
1067
     */
 
1068
    if (RTCounter == 0)
 
1069
    {
 
1070
        RTCounter = CreateNewResourceType(FreeCounter);
 
1071
        if (RTCounter == 0)
 
1072
        {
 
1073
            return (pointer)NULL;
 
1074
        }
 
1075
    }
 
1076
 
 
1077
    pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial);
 
1078
 
 
1079
    if (pCounter)
 
1080
    {
 
1081
        SysCounterInfo *psci;
 
1082
 
 
1083
        psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo));
 
1084
        if (!psci)
 
1085
        {
 
1086
            FreeResource(pCounter->id, RT_NONE);
 
1087
            return (pointer) pCounter;
 
1088
        }
 
1089
        pCounter->pSysCounterInfo = psci;
 
1090
        psci->name = name;
 
1091
        psci->resolution = resolution;
 
1092
        psci->counterType = counterType;
 
1093
        psci->QueryValue = QueryValue;
 
1094
        psci->BracketValues = BracketValues;
 
1095
        XSyncMaxValue(&psci->bracket_greater);
 
1096
        XSyncMinValue(&psci->bracket_less);
 
1097
        SysCounterList[SyncNumSystemCounters++] = pCounter;
 
1098
    }
 
1099
    return (pointer) pCounter;
 
1100
}
 
1101
 
 
1102
void
 
1103
SyncDestroySystemCounter(pSysCounter)
 
1104
    pointer pSysCounter;
 
1105
{
 
1106
    SyncCounter *pCounter = (SyncCounter *)pSysCounter;
 
1107
    FreeResource(pCounter->id, RT_NONE);
 
1108
}
 
1109
 
 
1110
static void
 
1111
SyncComputeBracketValues(pCounter, startOver)
 
1112
    SyncCounter *pCounter;
 
1113
    Bool startOver;
 
1114
{
 
1115
    SyncTriggerList *pCur;
 
1116
    SyncTrigger *pTrigger;
 
1117
    SysCounterInfo *psci = pCounter->pSysCounterInfo;
 
1118
    CARD64 *pnewgtval = NULL;
 
1119
    CARD64 *pnewltval = NULL;
 
1120
    SyncCounterType ct;
 
1121
 
 
1122
    if (!pCounter)
 
1123
        return;
 
1124
 
 
1125
    ct = pCounter->pSysCounterInfo->counterType;
 
1126
    if (ct == XSyncCounterNeverChanges)
 
1127
        return;
 
1128
 
 
1129
    if (startOver)
 
1130
    {
 
1131
        XSyncMaxValue(&psci->bracket_greater);
 
1132
        XSyncMinValue(&psci->bracket_less);
 
1133
    }
 
1134
 
 
1135
    for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next)
 
1136
    {
 
1137
        pTrigger = pCur->pTrigger;
 
1138
        
 
1139
        if (pTrigger->test_type == XSyncPositiveComparison &&
 
1140
            ct != XSyncCounterNeverIncreases)
 
1141
        {
 
1142
            if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
 
1143
                XSyncValueLessThan(pTrigger->test_value,
 
1144
                                   psci->bracket_greater))
 
1145
            {
 
1146
                psci->bracket_greater = pTrigger->test_value;
 
1147
                pnewgtval = &psci->bracket_greater;
 
1148
            }
 
1149
        }
 
1150
        else if (pTrigger->test_type == XSyncNegativeComparison &&
 
1151
                 ct != XSyncCounterNeverDecreases)
 
1152
        {
 
1153
            if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
 
1154
                XSyncValueGreaterThan(pTrigger->test_value,
 
1155
                                      psci->bracket_less))
 
1156
            {
 
1157
                psci->bracket_less = pTrigger->test_value;
 
1158
                pnewltval = &psci->bracket_less;
 
1159
            }
 
1160
        }
 
1161
        else if ( (pTrigger->test_type == XSyncPositiveTransition &&
 
1162
                   ct != XSyncCounterNeverIncreases)
 
1163
                 ||
 
1164
                 (pTrigger->test_type == XSyncNegativeTransition &&
 
1165
                  ct != XSyncCounterNeverDecreases)
 
1166
                 )
 
1167
        {
 
1168
            if (XSyncValueLessThan(pCounter->value, pTrigger->test_value))
 
1169
            {
 
1170
                if (XSyncValueLessThan(pTrigger->test_value,
 
1171
                                       psci->bracket_greater))
 
1172
                {
 
1173
                    psci->bracket_greater = pTrigger->test_value;
 
1174
                    pnewgtval = &psci->bracket_greater;
 
1175
                }
 
1176
                else
 
1177
                if (XSyncValueGreaterThan(pTrigger->test_value,
 
1178
                                          psci->bracket_less))
 
1179
                {
 
1180
                    psci->bracket_less = pTrigger->test_value;
 
1181
                    pnewltval = &psci->bracket_less;
 
1182
                }
 
1183
            }
 
1184
        }
 
1185
    } /* end for each trigger */
 
1186
 
 
1187
    if (pnewgtval || pnewltval)
 
1188
    {
 
1189
        (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
 
1190
    }
 
1191
}
 
1192
 
 
1193
/*
 
1194
 * *****  Resource delete functions
 
1195
 */
 
1196
 
 
1197
/* ARGSUSED */
 
1198
static int
 
1199
FreeAlarm(addr, id)
 
1200
    pointer         addr;
 
1201
    XID             id;
 
1202
{
 
1203
    SyncAlarm      *pAlarm = (SyncAlarm *) addr;
 
1204
 
 
1205
    pAlarm->state = XSyncAlarmDestroyed;
 
1206
 
 
1207
    SyncSendAlarmNotifyEvents(pAlarm);
 
1208
 
 
1209
    /* delete event selections */
 
1210
 
 
1211
    while (pAlarm->pEventClients)
 
1212
        FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
 
1213
 
 
1214
    SyncDeleteTriggerFromCounter(&pAlarm->trigger);
 
1215
 
 
1216
    xfree(pAlarm);
 
1217
    return Success;
 
1218
}
 
1219
 
 
1220
 
 
1221
/*
 
1222
 * ** Cleanup after the destruction of a Counter
 
1223
 */
 
1224
/* ARGSUSED */
 
1225
static int
 
1226
FreeCounter(env, id)
 
1227
    pointer         env;
 
1228
    XID             id;
 
1229
{
 
1230
    SyncCounter     *pCounter = (SyncCounter *) env;
 
1231
    SyncTriggerList *ptl, *pnext;
 
1232
 
 
1233
    pCounter->beingDestroyed = TRUE;
 
1234
    /* tell all the counter's triggers that the counter has been destroyed */
 
1235
    for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
 
1236
    {
 
1237
        (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
 
1238
        pnext = ptl->next;
 
1239
        xfree(ptl); /* destroy the trigger list as we go */
 
1240
    }
 
1241
    if (IsSystemCounter(pCounter))
 
1242
    {
 
1243
        int i, found = 0;
 
1244
 
 
1245
        xfree(pCounter->pSysCounterInfo);
 
1246
 
 
1247
        /* find the counter in the list of system counters and remove it */
 
1248
 
 
1249
        if (SysCounterList)
 
1250
        {
 
1251
            for (i = 0; i < SyncNumSystemCounters; i++)
 
1252
            {
 
1253
                if (SysCounterList[i] == pCounter)
 
1254
                {
 
1255
                    found = i;
 
1256
                    break;
 
1257
                }
 
1258
            }
 
1259
            if (found < (SyncNumSystemCounters-1))
 
1260
            {
 
1261
                for (i = found; i < SyncNumSystemCounters-1; i++)
 
1262
                {
 
1263
                    SysCounterList[i] = SysCounterList[i+1];
 
1264
                }
 
1265
            }
 
1266
        }
 
1267
        SyncNumSystemCounters--;
 
1268
    }
 
1269
    xfree(pCounter);
 
1270
    return Success;
 
1271
}
 
1272
 
 
1273
/*
 
1274
 * ** Cleanup after Await
 
1275
 */
 
1276
/* ARGSUSED */
 
1277
static int
 
1278
FreeAwait(addr, id)
 
1279
    pointer         addr;
 
1280
    XID             id;
 
1281
{
 
1282
    SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
 
1283
    SyncAwait *pAwait;
 
1284
    int numwaits;
 
1285
 
 
1286
    pAwait = &(pAwaitUnion+1)->await; /* first await on list */
 
1287
 
 
1288
    /* remove triggers from counters */
 
1289
 
 
1290
    for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
 
1291
         numwaits--, pAwait++)
 
1292
    {
 
1293
        /* If the counter is being destroyed, FreeCounter will delete 
 
1294
         * the trigger list itself, so don't do it here.
 
1295
         */
 
1296
        SyncCounter *pCounter = pAwait->trigger.pCounter;
 
1297
        if (pCounter && !pCounter->beingDestroyed)
 
1298
            SyncDeleteTriggerFromCounter(&pAwait->trigger);
 
1299
    }
 
1300
    xfree(pAwaitUnion);
 
1301
    return Success;
 
1302
}
 
1303
 
 
1304
/* loosely based on dix/events.c/OtherClientGone */
 
1305
static int
 
1306
FreeAlarmClient(value, id)
 
1307
    pointer value; /* must conform to DeleteType */
 
1308
    XID   id;
 
1309
{
 
1310
    SyncAlarm *pAlarm = (SyncAlarm *)value;
 
1311
    SyncAlarmClientList *pCur, *pPrev;
 
1312
 
 
1313
    for (pPrev = NULL, pCur = pAlarm->pEventClients;
 
1314
         pCur;
 
1315
         pPrev = pCur, pCur = pCur->next)
 
1316
    {
 
1317
        if (pCur->delete_id == id)
 
1318
        {
 
1319
            if (pPrev)
 
1320
                pPrev->next = pCur->next;
 
1321
            else
 
1322
                pAlarm->pEventClients = pCur->next;
 
1323
            xfree(pCur);
 
1324
            return(Success);
 
1325
        }
 
1326
    }
 
1327
    FatalError("alarm client not on event list");
 
1328
    /*NOTREACHED*/
 
1329
}
 
1330
 
 
1331
 
 
1332
/*
 
1333
 * *****  Proc functions
 
1334
 */
 
1335
 
 
1336
 
 
1337
/*
 
1338
 * ** Initialize the extension
 
1339
 */
 
1340
static int 
 
1341
ProcSyncInitialize(client)
 
1342
    ClientPtr       client;
 
1343
{
 
1344
    xSyncInitializeReply  rep;
 
1345
    int   n;
 
1346
 
 
1347
    REQUEST_SIZE_MATCH(xSyncInitializeReq);
 
1348
 
 
1349
    rep.type = X_Reply;
 
1350
    rep.sequenceNumber = client->sequence;
 
1351
    rep.majorVersion = SYNC_MAJOR_VERSION;
 
1352
    rep.minorVersion = SYNC_MINOR_VERSION;
 
1353
    rep.length = 0;
 
1354
 
 
1355
    if (client->swapped)
 
1356
    {
 
1357
        swaps(&rep.sequenceNumber, n);
 
1358
    }
 
1359
    WriteToClient(client, sizeof(rep), (char *) &rep);
 
1360
    return (client->noClientException);
 
1361
}
 
1362
 
 
1363
/*
 
1364
 * ** Get list of system counters available through the extension
 
1365
 */
 
1366
static int 
 
1367
ProcSyncListSystemCounters(client)
 
1368
    ClientPtr       client;
 
1369
{
 
1370
    xSyncListSystemCountersReply  rep;
 
1371
    int i, len;
 
1372
    xSyncSystemCounter *list = NULL, *walklist = NULL;
 
1373
    
 
1374
    REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
 
1375
 
 
1376
    rep.type = X_Reply;
 
1377
    rep.sequenceNumber = client->sequence;
 
1378
    rep.nCounters = SyncNumSystemCounters;
 
1379
 
 
1380
    for (i = len = 0; i < SyncNumSystemCounters; i++)
 
1381
    {
 
1382
        char *name = SysCounterList[i]->pSysCounterInfo->name;
 
1383
        /* pad to 4 byte boundary */
 
1384
        len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3;
 
1385
    }
 
1386
 
 
1387
    if (len)
 
1388
    {
 
1389
        walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len);
 
1390
        if (!list)
 
1391
            return BadAlloc;
 
1392
    }
 
1393
 
 
1394
    rep.length = len >> 2;
 
1395
 
 
1396
    if (client->swapped)
 
1397
    {
 
1398
        register char n;
 
1399
        swaps(&rep.sequenceNumber, n);
 
1400
        swapl(&rep.length, n);
 
1401
        swapl(&rep.nCounters, n);
 
1402
    }
 
1403
 
 
1404
    for (i = 0; i < SyncNumSystemCounters; i++)
 
1405
    {
 
1406
        int namelen;
 
1407
        char *pname_in_reply;
 
1408
        SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
 
1409
 
 
1410
        walklist->counter = SysCounterList[i]->id;
 
1411
        walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
 
1412
        walklist->resolution_lo = XSyncValueLow32(psci->resolution);
 
1413
        namelen = strlen(psci->name);
 
1414
        walklist->name_length = namelen;
 
1415
 
 
1416
        if (client->swapped)
 
1417
        {
 
1418
            register char n;
 
1419
            swapl(&walklist->counter, n);
 
1420
            swapl(&walklist->resolution_hi, n);
 
1421
            swapl(&walklist->resolution_lo, n);
 
1422
            swaps(&walklist->name_length, n);
 
1423
        }
 
1424
 
 
1425
        pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter;
 
1426
        strncpy(pname_in_reply, psci->name, namelen);
 
1427
        walklist = (xSyncSystemCounter *) (((char *)walklist) + 
 
1428
                                ((sz_xSyncSystemCounter + namelen + 3) & ~3));
 
1429
    }
 
1430
 
 
1431
    WriteToClient(client, sizeof(rep), (char *) &rep);
 
1432
    if (len) 
 
1433
    {
 
1434
        WriteToClient(client, len, (char *) list);
 
1435
        DEALLOCATE_LOCAL(list);
 
1436
    }
 
1437
 
 
1438
    return (client->noClientException);
 
1439
}
 
1440
 
 
1441
/*
 
1442
 * ** Set client Priority
 
1443
 */
 
1444
static int 
 
1445
ProcSyncSetPriority(client)
 
1446
    ClientPtr       client;
 
1447
{
 
1448
    REQUEST(xSyncSetPriorityReq);
 
1449
    ClientPtr priorityclient;
 
1450
 
 
1451
    REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
 
1452
 
 
1453
    if (stuff->id == None)
 
1454
        priorityclient = client;
 
1455
    else if (!(priorityclient = LookupClient(stuff->id, client)))
 
1456
    {
 
1457
        client->errorValue = stuff->id;
 
1458
        return BadMatch;
 
1459
    }
 
1460
 
 
1461
    if (priorityclient->priority != stuff->priority)
 
1462
    {
 
1463
        priorityclient->priority = stuff->priority;
 
1464
 
 
1465
        /*  The following will force the server back into WaitForSomething
 
1466
         *  so that the change in this client's priority is immediately
 
1467
         *  reflected.
 
1468
         */
 
1469
        isItTimeToYield = TRUE;
 
1470
        dispatchException |= DE_PRIORITYCHANGE;
 
1471
    }
 
1472
    return Success;
 
1473
}
 
1474
 
 
1475
/*
 
1476
 * ** Get client Priority
 
1477
 */
 
1478
static int 
 
1479
ProcSyncGetPriority(client)
 
1480
    ClientPtr       client;
 
1481
{
 
1482
    REQUEST(xSyncGetPriorityReq);
 
1483
    xSyncGetPriorityReply rep;
 
1484
    ClientPtr priorityclient;
 
1485
 
 
1486
    REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
 
1487
 
 
1488
    if (stuff->id == None)
 
1489
        priorityclient = client;
 
1490
    else if (!(priorityclient = LookupClient(stuff->id, client)))
 
1491
    {
 
1492
        client->errorValue = stuff->id;
 
1493
        return BadMatch;
 
1494
    }
 
1495
 
 
1496
    rep.type = X_Reply;
 
1497
    rep.length = 0;
 
1498
    rep.sequenceNumber = client->sequence;
 
1499
    rep.priority = priorityclient->priority;
 
1500
 
 
1501
    if (client->swapped)
 
1502
    {
 
1503
        register char n;
 
1504
        swaps(&rep.sequenceNumber, n);
 
1505
        swapl(&rep.priority, n);
 
1506
    }
 
1507
 
 
1508
    WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
 
1509
 
 
1510
    return (client->noClientException);
 
1511
}
 
1512
 
 
1513
/*
 
1514
 * ** Create a new counter
 
1515
 */
 
1516
static int 
 
1517
ProcSyncCreateCounter(client)
 
1518
    ClientPtr       client;
 
1519
{
 
1520
    REQUEST(xSyncCreateCounterReq);
 
1521
    CARD64          initial;
 
1522
 
 
1523
    REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
 
1524
 
 
1525
    LEGAL_NEW_RESOURCE(stuff->cid, client);
 
1526
 
 
1527
    XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
 
1528
    if (!SyncCreateCounter(client, stuff->cid, initial))
 
1529
        return BadAlloc;
 
1530
 
 
1531
    return (client->noClientException);
 
1532
}
 
1533
 
 
1534
/*
 
1535
 * ** Set Counter value
 
1536
 */
 
1537
static int 
 
1538
ProcSyncSetCounter(client)
 
1539
    ClientPtr       client;
 
1540
{
 
1541
    REQUEST(xSyncSetCounterReq);
 
1542
    SyncCounter    *pCounter;
 
1543
    CARD64         newvalue;
 
1544
 
 
1545
    REQUEST_SIZE_MATCH(xSyncSetCounterReq);
 
1546
 
 
1547
    pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid,
 
1548
                                           RTCounter, SecurityWriteAccess);
 
1549
    if (pCounter == NULL)
 
1550
    {
 
1551
        client->errorValue = stuff->cid;
 
1552
        return SyncErrorBase + XSyncBadCounter;
 
1553
    }
 
1554
 
 
1555
    if (IsSystemCounter(pCounter))
 
1556
    {
 
1557
        client->errorValue = stuff->cid;
 
1558
        return BadAccess;
 
1559
    }
 
1560
 
 
1561
    XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
 
1562
    SyncChangeCounter(pCounter, newvalue);
 
1563
    return Success;
 
1564
}
 
1565
 
 
1566
/*
 
1567
 * ** Change Counter value
 
1568
 */
 
1569
static int 
 
1570
ProcSyncChangeCounter(client)
 
1571
    ClientPtr       client;
 
1572
{
 
1573
    REQUEST(xSyncChangeCounterReq);
 
1574
    SyncCounter    *pCounter;
 
1575
    CARD64          newvalue;
 
1576
    Bool            overflow;
 
1577
 
 
1578
    REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
 
1579
 
 
1580
    pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid,
 
1581
                                            RTCounter, SecurityWriteAccess);
 
1582
    if (pCounter == NULL)
 
1583
    {
 
1584
        client->errorValue = stuff->cid;
 
1585
        return SyncErrorBase + XSyncBadCounter;
 
1586
    }
 
1587
 
 
1588
    if (IsSystemCounter(pCounter))
 
1589
    {
 
1590
        client->errorValue = stuff->cid;
 
1591
        return BadAccess;
 
1592
    }
 
1593
 
 
1594
    XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
 
1595
    XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
 
1596
    if (overflow)
 
1597
    {
 
1598
        /* XXX 64 bit value can't fit in 32 bits; do the best we can */
 
1599
        client->errorValue = stuff->value_hi; 
 
1600
        return BadValue;
 
1601
    }
 
1602
    SyncChangeCounter(pCounter, newvalue);
 
1603
    return Success;
 
1604
}
 
1605
 
 
1606
/*
 
1607
 * ** Destroy a counter
 
1608
 */
 
1609
static int 
 
1610
ProcSyncDestroyCounter(client)
 
1611
    ClientPtr       client;
 
1612
{
 
1613
    REQUEST(xSyncDestroyCounterReq);
 
1614
    SyncCounter    *pCounter;
 
1615
 
 
1616
    REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
 
1617
 
 
1618
    pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
 
1619
                                           RTCounter, SecurityDestroyAccess);
 
1620
    if (pCounter == NULL)
 
1621
    {
 
1622
        client->errorValue = stuff->counter;
 
1623
        return SyncErrorBase + XSyncBadCounter;
 
1624
    }
 
1625
    if (IsSystemCounter(pCounter))
 
1626
    {
 
1627
        client->errorValue = stuff->counter;
 
1628
        return BadAccess;
 
1629
    }
 
1630
    FreeResource(pCounter->id, RT_NONE);
 
1631
    return Success;
 
1632
}
 
1633
 
 
1634
 
 
1635
/*
 
1636
 * ** Await
 
1637
 */
 
1638
static int 
 
1639
ProcSyncAwait(client)
 
1640
    ClientPtr       client;
 
1641
{
 
1642
    REQUEST(xSyncAwaitReq);
 
1643
    int             len, items;
 
1644
    int             i;
 
1645
    xSyncWaitCondition *pProtocolWaitConds;
 
1646
    SyncAwaitUnion *pAwaitUnion;
 
1647
    SyncAwait      *pAwait;
 
1648
    int            status;
 
1649
 
 
1650
    REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
 
1651
 
 
1652
    len = client->req_len << 2;
 
1653
    len -= sz_xSyncAwaitReq;
 
1654
    items = len / sz_xSyncWaitCondition;
 
1655
 
 
1656
    if (items * sz_xSyncWaitCondition != len)
 
1657
    {
 
1658
        return BadLength;
 
1659
    }
 
1660
    if (items == 0)
 
1661
    {
 
1662
        client->errorValue = items; /* XXX protocol change */
 
1663
        return BadValue;
 
1664
    }
 
1665
 
 
1666
    pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
 
1667
 
 
1668
    /*  all the memory for the entire await list is allocated 
 
1669
     *  here in one chunk
 
1670
     */
 
1671
    pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion));
 
1672
    if (!pAwaitUnion)
 
1673
        return BadAlloc;
 
1674
 
 
1675
    /* first item is the header, remainder are real wait conditions */
 
1676
 
 
1677
    pAwaitUnion->header.delete_id = FakeClientID(client->index);
 
1678
    if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
 
1679
    {
 
1680
        xfree(pAwaitUnion);
 
1681
        return BadAlloc;
 
1682
    }
 
1683
 
 
1684
    /* don't need to do any more memory allocation for this request! */
 
1685
 
 
1686
    pAwaitUnion->header.client = client;
 
1687
    pAwaitUnion->header.num_waitconditions = 0;
 
1688
 
 
1689
    pAwait = &(pAwaitUnion+1)->await; /* skip over header */
 
1690
    for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
 
1691
    {
 
1692
        if (pProtocolWaitConds->counter == None) /* XXX protocol change */
 
1693
        {
 
1694
            /*  this should take care of removing any triggers created by
 
1695
             *  this request that have already been registered on counters
 
1696
             */
 
1697
            FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
 
1698
            client->errorValue = pProtocolWaitConds->counter;
 
1699
            return SyncErrorBase + XSyncBadCounter;
 
1700
        }
 
1701
 
 
1702
        /* sanity checks are in SyncInitTrigger */
 
1703
        pAwait->trigger.pCounter = NULL;
 
1704
        pAwait->trigger.value_type = pProtocolWaitConds->value_type;
 
1705
        XSyncIntsToValue(&pAwait->trigger.wait_value,
 
1706
                         pProtocolWaitConds->wait_value_lo,
 
1707
                         pProtocolWaitConds->wait_value_hi);
 
1708
        pAwait->trigger.test_type = pProtocolWaitConds->test_type;
 
1709
 
 
1710
        status = SyncInitTrigger(client, &pAwait->trigger,
 
1711
                         pProtocolWaitConds->counter, XSyncCAAllTrigger);
 
1712
        if (status != Success)
 
1713
        {
 
1714
            /*  this should take care of removing any triggers created by
 
1715
             *  this request that have already been registered on counters
 
1716
             */
 
1717
            FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
 
1718
            return status;
 
1719
        }
 
1720
        /* this is not a mistake -- same function works for both cases */
 
1721
        pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
 
1722
        pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
 
1723
        XSyncIntsToValue(&pAwait->event_threshold,
 
1724
                         pProtocolWaitConds->event_threshold_lo,
 
1725
                         pProtocolWaitConds->event_threshold_hi);
 
1726
        pAwait->pHeader = &pAwaitUnion->header;
 
1727
        pAwaitUnion->header.num_waitconditions++;
 
1728
    }
 
1729
 
 
1730
    IgnoreClient(client);
 
1731
 
 
1732
    /* see if any of the triggers are already true */
 
1733
 
 
1734
    pAwait = &(pAwaitUnion+1)->await; /* skip over header */
 
1735
    for (i = 0; i < items; i++, pAwait++)
 
1736
    {
 
1737
        /*  don't have to worry about NULL counters because the request
 
1738
         *  errors before we get here out if they occur
 
1739
         */
 
1740
        if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger,
 
1741
                                            pAwait->trigger.pCounter->value))
 
1742
        {
 
1743
            (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
 
1744
            break; /* once is enough */
 
1745
        }
 
1746
    }
 
1747
    return Success;
 
1748
}
 
1749
 
 
1750
 
 
1751
/*
 
1752
 * ** Query a counter
 
1753
 */
 
1754
static int 
 
1755
ProcSyncQueryCounter(client)
 
1756
    ClientPtr       client;
 
1757
{
 
1758
    REQUEST(xSyncQueryCounterReq);
 
1759
    xSyncQueryCounterReply rep;
 
1760
    SyncCounter    *pCounter;
 
1761
 
 
1762
    REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
 
1763
 
 
1764
    pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
 
1765
                                            RTCounter, SecurityReadAccess);
 
1766
    if (pCounter == NULL)
 
1767
    {
 
1768
        client->errorValue = stuff->counter;
 
1769
        return SyncErrorBase + XSyncBadCounter;
 
1770
    }
 
1771
 
 
1772
    rep.type = X_Reply;
 
1773
    rep.length = 0;
 
1774
    rep.sequenceNumber = client->sequence;
 
1775
 
 
1776
    /* if system counter, ask it what the current value is */
 
1777
 
 
1778
    if (IsSystemCounter(pCounter))
 
1779
    {
 
1780
        (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
 
1781
                                                  &pCounter->value);
 
1782
    }
 
1783
 
 
1784
    rep.value_hi = XSyncValueHigh32(pCounter->value);
 
1785
    rep.value_lo = XSyncValueLow32(pCounter->value);
 
1786
    if (client->swapped)
 
1787
    {
 
1788
        register char n;
 
1789
        swaps(&rep.sequenceNumber, n);
 
1790
        swapl(&rep.length, n);
 
1791
        swapl(&rep.value_hi, n);
 
1792
        swapl(&rep.value_lo, n);
 
1793
    }
 
1794
    WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
 
1795
    return (client->noClientException);
 
1796
}
 
1797
 
 
1798
 
 
1799
/*
 
1800
 * ** Create Alarm
 
1801
 */
 
1802
static int 
 
1803
ProcSyncCreateAlarm(client)
 
1804
    ClientPtr       client;
 
1805
{
 
1806
    REQUEST(xSyncCreateAlarmReq);
 
1807
    SyncAlarm      *pAlarm;
 
1808
    int             status;
 
1809
    unsigned long   len, vmask;
 
1810
    SyncTrigger     *pTrigger;
 
1811
 
 
1812
    REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
 
1813
 
 
1814
    LEGAL_NEW_RESOURCE(stuff->id, client);
 
1815
 
 
1816
    vmask = stuff->valueMask;
 
1817
    len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2);
 
1818
    /* the "extra" call to Ones accounts for the presence of 64 bit values */
 
1819
    if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
 
1820
        return BadLength;
 
1821
 
 
1822
    if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm))))
 
1823
    {
 
1824
        return BadAlloc;
 
1825
    }
 
1826
 
 
1827
    /* set up defaults */
 
1828
 
 
1829
    pTrigger = &pAlarm->trigger;
 
1830
    pTrigger->pCounter = NULL;
 
1831
    pTrigger->value_type = XSyncAbsolute;
 
1832
    XSyncIntToValue(&pTrigger->wait_value, 0L);
 
1833
    pTrigger->test_type = XSyncPositiveComparison;
 
1834
    pTrigger->TriggerFired = SyncAlarmTriggerFired;
 
1835
    pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
 
1836
    status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger);
 
1837
    if (status != Success)
 
1838
    {
 
1839
        xfree(pAlarm);
 
1840
        return status;
 
1841
    }
 
1842
 
 
1843
    pAlarm->client = client;
 
1844
    pAlarm->alarm_id = stuff->id;
 
1845
    XSyncIntToValue(&pAlarm->delta, 1L);
 
1846
    pAlarm->events = TRUE;
 
1847
    pAlarm->state = XSyncAlarmInactive;
 
1848
    pAlarm->pEventClients = NULL;
 
1849
    status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
 
1850
                                       (CARD32 *)&stuff[1]);
 
1851
    if (status != Success)
 
1852
    {
 
1853
        xfree(pAlarm);
 
1854
        return status;
 
1855
    }
 
1856
 
 
1857
    if (!AddResource(stuff->id, RTAlarm, pAlarm))
 
1858
    {
 
1859
        xfree(pAlarm);
 
1860
        return BadAlloc;
 
1861
    }
 
1862
 
 
1863
    /*  see if alarm already triggered.  NULL counter will not trigger
 
1864
     *  in CreateAlarm and sets alarm state to Inactive.
 
1865
     */
 
1866
 
 
1867
    if (!pTrigger->pCounter)
 
1868
    {
 
1869
        pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
 
1870
    }
 
1871
    else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value))
 
1872
    {
 
1873
        (*pTrigger->TriggerFired)(pTrigger);
 
1874
    }
 
1875
 
 
1876
    return Success;
 
1877
}
 
1878
 
 
1879
/*
 
1880
 * ** Change Alarm
 
1881
 */
 
1882
static int 
 
1883
ProcSyncChangeAlarm(client)
 
1884
    ClientPtr       client;
 
1885
{
 
1886
    REQUEST(xSyncChangeAlarmReq);
 
1887
    SyncAlarm   *pAlarm;
 
1888
    long        vmask;
 
1889
    int         len, status;
 
1890
 
 
1891
    REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
 
1892
 
 
1893
    if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
 
1894
                                              RTAlarm, SecurityWriteAccess)))
 
1895
    {
 
1896
        client->errorValue = stuff->alarm;
 
1897
        return SyncErrorBase + XSyncBadAlarm;
 
1898
    }
 
1899
 
 
1900
    vmask = stuff->valueMask;
 
1901
    len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2);
 
1902
    /* the "extra" call to Ones accounts for the presence of 64 bit values */
 
1903
    if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
 
1904
        return BadLength;
 
1905
 
 
1906
    if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, 
 
1907
                                            (CARD32 *)&stuff[1])) != Success)
 
1908
        return status;
 
1909
 
 
1910
    /*  see if alarm already triggered.  NULL counter WILL trigger
 
1911
     *  in ChangeAlarm.
 
1912
     */
 
1913
 
 
1914
    if (!pAlarm->trigger.pCounter ||
 
1915
        (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger,
 
1916
                                        pAlarm->trigger.pCounter->value))
 
1917
    {
 
1918
        (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
 
1919
    }
 
1920
    return Success;
 
1921
}
 
1922
 
 
1923
static int 
 
1924
ProcSyncQueryAlarm(client)
 
1925
    ClientPtr       client;
 
1926
{
 
1927
    REQUEST(xSyncQueryAlarmReq);
 
1928
    SyncAlarm      *pAlarm;
 
1929
    xSyncQueryAlarmReply rep;
 
1930
    SyncTrigger    *pTrigger;
 
1931
 
 
1932
    REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
 
1933
 
 
1934
    pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
 
1935
                                                RTAlarm, SecurityReadAccess);
 
1936
    if (!pAlarm)
 
1937
    {
 
1938
        client->errorValue = stuff->alarm;
 
1939
        return (SyncErrorBase + XSyncBadAlarm);
 
1940
    }
 
1941
 
 
1942
    rep.type = X_Reply;
 
1943
    rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2;
 
1944
    rep.sequenceNumber = client->sequence;
 
1945
 
 
1946
    pTrigger = &pAlarm->trigger;
 
1947
    rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None;
 
1948
 
 
1949
#if 0 /* XXX unclear what to do, depends on whether relative value-types
 
1950
       * are "consumed" immediately and are considered absolute from then
 
1951
       * on.
 
1952
       */
 
1953
    rep.value_type = pTrigger->value_type;
 
1954
    rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value);
 
1955
    rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value);
 
1956
#else
 
1957
    rep.value_type = XSyncAbsolute;
 
1958
    rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
 
1959
    rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
 
1960
#endif
 
1961
 
 
1962
    rep.test_type = pTrigger->test_type;
 
1963
    rep.delta_hi = XSyncValueHigh32(pAlarm->delta);
 
1964
    rep.delta_lo = XSyncValueLow32(pAlarm->delta);
 
1965
    rep.events = pAlarm->events;
 
1966
    rep.state = pAlarm->state;
 
1967
 
 
1968
    if (client->swapped)
 
1969
    {
 
1970
        register char n;
 
1971
        swaps(&rep.sequenceNumber, n);
 
1972
        swapl(&rep.length, n);
 
1973
        swapl(&rep.counter, n);
 
1974
        swapl(&rep.wait_value_hi, n);
 
1975
        swapl(&rep.wait_value_lo, n);
 
1976
        swapl(&rep.test_type, n);
 
1977
        swapl(&rep.delta_hi, n);
 
1978
        swapl(&rep.delta_lo, n);
 
1979
    }
 
1980
 
 
1981
    WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
 
1982
    return (client->noClientException);
 
1983
}
 
1984
 
 
1985
 
 
1986
static int 
 
1987
ProcSyncDestroyAlarm(client)
 
1988
    ClientPtr       client;
 
1989
{
 
1990
    REQUEST(xSyncDestroyAlarmReq);
 
1991
 
 
1992
    REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
 
1993
 
 
1994
    if (!((SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
 
1995
                                              RTAlarm, SecurityDestroyAccess)))
 
1996
    {
 
1997
        client->errorValue = stuff->alarm;
 
1998
        return SyncErrorBase + XSyncBadAlarm;
 
1999
    }
 
2000
 
 
2001
    FreeResource(stuff->alarm, RT_NONE);
 
2002
    return (client->noClientException);
 
2003
}
 
2004
 
 
2005
/*
 
2006
 * ** Given an extension request, call the appropriate request procedure
 
2007
 */
 
2008
static int 
 
2009
ProcSyncDispatch(client)
 
2010
    ClientPtr       client;
 
2011
{
 
2012
    REQUEST(xReq);
 
2013
 
 
2014
    switch (stuff->data)
 
2015
    {
 
2016
 
 
2017
      case X_SyncInitialize:
 
2018
        return ProcSyncInitialize(client);
 
2019
      case X_SyncListSystemCounters:
 
2020
        return ProcSyncListSystemCounters(client);
 
2021
      case X_SyncCreateCounter:
 
2022
        return ProcSyncCreateCounter(client);
 
2023
      case X_SyncSetCounter:
 
2024
        return ProcSyncSetCounter(client);
 
2025
      case X_SyncChangeCounter:
 
2026
        return ProcSyncChangeCounter(client);
 
2027
      case X_SyncQueryCounter:
 
2028
        return ProcSyncQueryCounter(client);
 
2029
      case X_SyncDestroyCounter:
 
2030
        return ProcSyncDestroyCounter(client);
 
2031
      case X_SyncAwait:
 
2032
        return ProcSyncAwait(client);
 
2033
      case X_SyncCreateAlarm:
 
2034
        return ProcSyncCreateAlarm(client);
 
2035
      case X_SyncChangeAlarm:
 
2036
        return ProcSyncChangeAlarm(client);
 
2037
      case X_SyncQueryAlarm:
 
2038
        return ProcSyncQueryAlarm(client);
 
2039
      case X_SyncDestroyAlarm:
 
2040
        return ProcSyncDestroyAlarm(client);
 
2041
      case X_SyncSetPriority:
 
2042
        return ProcSyncSetPriority(client);
 
2043
      case X_SyncGetPriority:
 
2044
        return ProcSyncGetPriority(client);
 
2045
      default:
 
2046
        return BadRequest;
 
2047
    }
 
2048
}
 
2049
 
 
2050
/*
 
2051
 * Boring Swapping stuff ...
 
2052
 */
 
2053
 
 
2054
static int 
 
2055
SProcSyncInitialize(client)
 
2056
    ClientPtr       client;
 
2057
{
 
2058
    REQUEST(xSyncInitializeReq);
 
2059
    register char   n;
 
2060
 
 
2061
    swaps(&stuff->length, n);
 
2062
    REQUEST_SIZE_MATCH (xSyncInitializeReq);
 
2063
 
 
2064
    return ProcSyncInitialize(client);
 
2065
}
 
2066
 
 
2067
static int 
 
2068
SProcSyncListSystemCounters(client)
 
2069
    ClientPtr       client;
 
2070
{
 
2071
    REQUEST(xSyncListSystemCountersReq);
 
2072
    register char   n;
 
2073
 
 
2074
    swaps(&stuff->length, n);
 
2075
    REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
 
2076
 
 
2077
    return ProcSyncListSystemCounters(client);
 
2078
}
 
2079
 
 
2080
static int 
 
2081
SProcSyncCreateCounter(client)
 
2082
    ClientPtr       client;
 
2083
{
 
2084
    REQUEST(xSyncCreateCounterReq);
 
2085
    register char   n;
 
2086
 
 
2087
    swaps(&stuff->length, n);
 
2088
    REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
 
2089
    swapl(&stuff->cid, n);
 
2090
    swapl(&stuff->initial_value_lo, n);
 
2091
    swapl(&stuff->initial_value_hi, n);
 
2092
 
 
2093
    return ProcSyncCreateCounter(client);
 
2094
}
 
2095
 
 
2096
static int 
 
2097
SProcSyncSetCounter(client)
 
2098
    ClientPtr       client;
 
2099
{
 
2100
    REQUEST(xSyncSetCounterReq);
 
2101
    register char   n;
 
2102
 
 
2103
    swaps(&stuff->length, n);
 
2104
    REQUEST_SIZE_MATCH (xSyncSetCounterReq);
 
2105
    swapl(&stuff->cid, n);
 
2106
    swapl(&stuff->value_lo, n);
 
2107
    swapl(&stuff->value_hi, n);
 
2108
 
 
2109
    return ProcSyncSetCounter(client);
 
2110
}
 
2111
 
 
2112
static int 
 
2113
SProcSyncChangeCounter(client)
 
2114
    ClientPtr       client;
 
2115
{
 
2116
    REQUEST(xSyncChangeCounterReq);
 
2117
    register char   n;
 
2118
 
 
2119
    swaps(&stuff->length, n);
 
2120
    REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
 
2121
    swapl(&stuff->cid, n);
 
2122
    swapl(&stuff->value_lo, n);
 
2123
    swapl(&stuff->value_hi, n);
 
2124
 
 
2125
    return ProcSyncChangeCounter(client);
 
2126
}
 
2127
 
 
2128
static int 
 
2129
SProcSyncQueryCounter(client)
 
2130
    ClientPtr       client;
 
2131
{
 
2132
    REQUEST(xSyncQueryCounterReq);
 
2133
    register char   n;
 
2134
 
 
2135
    swaps(&stuff->length, n);
 
2136
    REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
 
2137
    swapl(&stuff->counter, n);
 
2138
 
 
2139
    return ProcSyncQueryCounter(client);
 
2140
}
 
2141
 
 
2142
static int 
 
2143
SProcSyncDestroyCounter(client)
 
2144
    ClientPtr       client;
 
2145
{
 
2146
    REQUEST(xSyncDestroyCounterReq);
 
2147
    register char   n;
 
2148
 
 
2149
    swaps(&stuff->length, n);
 
2150
    REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
 
2151
    swapl(&stuff->counter, n);
 
2152
 
 
2153
    return ProcSyncDestroyCounter(client);
 
2154
}
 
2155
 
 
2156
static int 
 
2157
SProcSyncAwait(client)
 
2158
    ClientPtr       client;
 
2159
{
 
2160
    REQUEST(xSyncAwaitReq);
 
2161
    register char   n;
 
2162
 
 
2163
    swaps(&stuff->length, n);
 
2164
    REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
 
2165
    SwapRestL(stuff);
 
2166
 
 
2167
    return ProcSyncAwait(client);
 
2168
}
 
2169
 
 
2170
 
 
2171
static int 
 
2172
SProcSyncCreateAlarm(client)
 
2173
    ClientPtr       client;
 
2174
{
 
2175
    REQUEST(xSyncCreateAlarmReq);
 
2176
    register char   n;
 
2177
 
 
2178
    swaps(&stuff->length, n);
 
2179
    REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
 
2180
    swapl(&stuff->id, n);
 
2181
    swapl(&stuff->valueMask, n);
 
2182
    SwapRestL(stuff);
 
2183
 
 
2184
    return ProcSyncCreateAlarm(client);
 
2185
}
 
2186
 
 
2187
static int 
 
2188
SProcSyncChangeAlarm(client)
 
2189
    ClientPtr       client;
 
2190
{
 
2191
    REQUEST(xSyncChangeAlarmReq);
 
2192
    register char   n;
 
2193
 
 
2194
    swaps(&stuff->length, n);
 
2195
    REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
 
2196
    swapl(&stuff->alarm, n);
 
2197
    swapl(&stuff->valueMask, n);
 
2198
    SwapRestL(stuff);
 
2199
    return ProcSyncChangeAlarm(client);
 
2200
}
 
2201
 
 
2202
static int 
 
2203
SProcSyncQueryAlarm(client)
 
2204
    ClientPtr       client;
 
2205
{
 
2206
    REQUEST(xSyncQueryAlarmReq);
 
2207
    register char   n;
 
2208
 
 
2209
    swaps(&stuff->length, n);
 
2210
    REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
 
2211
    swapl(&stuff->alarm, n);
 
2212
 
 
2213
    return ProcSyncQueryAlarm(client);
 
2214
}
 
2215
 
 
2216
static int 
 
2217
SProcSyncDestroyAlarm(client)
 
2218
    ClientPtr       client;
 
2219
{
 
2220
    REQUEST(xSyncDestroyAlarmReq);
 
2221
    register char   n;
 
2222
 
 
2223
    swaps(&stuff->length, n);
 
2224
    REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
 
2225
    swapl(&stuff->alarm, n);
 
2226
 
 
2227
    return ProcSyncDestroyAlarm(client);
 
2228
}
 
2229
 
 
2230
static int 
 
2231
SProcSyncSetPriority(client)
 
2232
    ClientPtr       client;
 
2233
{
 
2234
    REQUEST(xSyncSetPriorityReq);
 
2235
    register char   n;
 
2236
 
 
2237
    swaps(&stuff->length, n);
 
2238
    REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
 
2239
    swapl(&stuff->id, n);
 
2240
    swapl(&stuff->priority, n);
 
2241
 
 
2242
    return ProcSyncSetPriority(client);
 
2243
}
 
2244
 
 
2245
static int 
 
2246
SProcSyncGetPriority(client)
 
2247
    ClientPtr       client;
 
2248
{
 
2249
    REQUEST(xSyncGetPriorityReq);
 
2250
    register char   n;
 
2251
 
 
2252
    swaps(&stuff->length, n);
 
2253
    REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
 
2254
    swapl(&stuff->id, n);
 
2255
 
 
2256
    return ProcSyncGetPriority(client);
 
2257
}
 
2258
 
 
2259
 
 
2260
static int 
 
2261
SProcSyncDispatch(client)
 
2262
    ClientPtr       client;
 
2263
{
 
2264
    REQUEST(xReq);
 
2265
 
 
2266
    switch (stuff->data)
 
2267
    {
 
2268
      case X_SyncInitialize:
 
2269
        return SProcSyncInitialize(client);
 
2270
      case X_SyncListSystemCounters:
 
2271
        return SProcSyncListSystemCounters(client);
 
2272
      case X_SyncCreateCounter:
 
2273
        return SProcSyncCreateCounter(client);
 
2274
      case X_SyncSetCounter:
 
2275
        return SProcSyncSetCounter(client);
 
2276
      case X_SyncChangeCounter:
 
2277
        return SProcSyncChangeCounter(client);
 
2278
      case X_SyncQueryCounter:
 
2279
        return SProcSyncQueryCounter(client);
 
2280
      case X_SyncDestroyCounter:
 
2281
        return SProcSyncDestroyCounter(client);
 
2282
      case X_SyncAwait:
 
2283
        return SProcSyncAwait(client);
 
2284
      case X_SyncCreateAlarm:
 
2285
        return SProcSyncCreateAlarm(client);
 
2286
      case X_SyncChangeAlarm:
 
2287
        return SProcSyncChangeAlarm(client);
 
2288
      case X_SyncQueryAlarm:
 
2289
        return SProcSyncQueryAlarm(client);
 
2290
      case X_SyncDestroyAlarm:
 
2291
        return SProcSyncDestroyAlarm(client);
 
2292
      case X_SyncSetPriority:
 
2293
        return SProcSyncSetPriority(client);
 
2294
      case X_SyncGetPriority:
 
2295
        return SProcSyncGetPriority(client);
 
2296
      default:
 
2297
        return BadRequest;
 
2298
    }
 
2299
}
 
2300
 
 
2301
/*
 
2302
 * Event Swapping
 
2303
 */
 
2304
 
 
2305
static void 
 
2306
SCounterNotifyEvent(from, to)
 
2307
    xSyncCounterNotifyEvent *from, *to;
 
2308
{
 
2309
    to->type = from->type;
 
2310
    to->kind = from->kind;
 
2311
    cpswaps(from->sequenceNumber, to->sequenceNumber);
 
2312
    cpswapl(from->counter, to->counter);
 
2313
    cpswapl(from->wait_value_lo, to->wait_value_lo);
 
2314
    cpswapl(from->wait_value_hi, to->wait_value_hi);
 
2315
    cpswapl(from->counter_value_lo, to->counter_value_lo);
 
2316
    cpswapl(from->counter_value_hi, to->counter_value_hi);
 
2317
    cpswapl(from->time, to->time);
 
2318
    cpswaps(from->count, to->count);
 
2319
    to->destroyed = from->destroyed;
 
2320
}
 
2321
 
 
2322
 
 
2323
static void 
 
2324
SAlarmNotifyEvent(from, to)
 
2325
    xSyncAlarmNotifyEvent *from, *to;
 
2326
{
 
2327
    to->type = from->type;
 
2328
    to->kind = from->kind;
 
2329
    cpswaps(from->sequenceNumber, to->sequenceNumber);
 
2330
    cpswapl(from->alarm, to->alarm);
 
2331
    cpswapl(from->counter_value_lo, to->counter_value_lo);
 
2332
    cpswapl(from->counter_value_hi, to->counter_value_hi);
 
2333
    cpswapl(from->alarm_value_lo, to->alarm_value_lo);
 
2334
    cpswapl(from->alarm_value_hi, to->alarm_value_hi);
 
2335
    cpswapl(from->time, to->time);
 
2336
    to->state = from->state;
 
2337
}
 
2338
 
 
2339
/*
 
2340
 * ** Close everything down. ** This is fairly simple for now.
 
2341
 */
 
2342
/* ARGSUSED */
 
2343
static void 
 
2344
SyncResetProc(extEntry)
 
2345
    ExtensionEntry *extEntry;
 
2346
{
 
2347
    xfree(SysCounterList);
 
2348
    SysCounterList = NULL;
 
2349
    RTCounter = 0;
 
2350
}
 
2351
 
 
2352
 
 
2353
/*
 
2354
 * ** Initialise the extension.
 
2355
 */
 
2356
void 
 
2357
SyncExtensionInit(INITARGS)
 
2358
{
 
2359
    ExtensionEntry *extEntry;
 
2360
 
 
2361
    if (RTCounter == 0)
 
2362
    {
 
2363
        RTCounter = CreateNewResourceType(FreeCounter);
 
2364
    }
 
2365
    RTAlarm = CreateNewResourceType(FreeAlarm);
 
2366
    RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN;
 
2367
    RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN;
 
2368
 
 
2369
    if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
 
2370
        RTAlarmClient == 0 ||
 
2371
        (extEntry = AddExtension(SYNC_NAME,
 
2372
                                 XSyncNumberEvents, XSyncNumberErrors,
 
2373
                                 ProcSyncDispatch, SProcSyncDispatch,
 
2374
                                 SyncResetProc,
 
2375
                                 StandardMinorOpcode)) == NULL)
 
2376
    {
 
2377
        ErrorF("Sync Extension %d.%d failed to Initialise\n",
 
2378
                SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
 
2379
        return;
 
2380
    }
 
2381
 
 
2382
    SyncEventBase = extEntry->eventBase;
 
2383
    SyncErrorBase = extEntry->errorBase;
 
2384
    EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
 
2385
    EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
 
2386
 
 
2387
    /*
 
2388
     * Although SERVERTIME is implemented by the OS layer, we initialise it
 
2389
     * here because doing it in OsInit() is too early. The resource database
 
2390
     * is not initialised when OsInit() is called. This is just about OK
 
2391
     * because there is always a servertime counter.
 
2392
     */
 
2393
    SyncInitServerTime();
 
2394
 
 
2395
#ifdef DEBUG
 
2396
    fprintf(stderr, "Sync Extension %d.%d\n",
 
2397
            SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
 
2398
#endif
 
2399
}
 
2400
 
 
2401
 
 
2402
/*
 
2403
 * ***** SERVERTIME implementation - should go in its own file in OS directory?
 
2404
 */
 
2405
 
 
2406
 
 
2407
 
 
2408
static pointer ServertimeCounter;
 
2409
static XSyncValue Now;
 
2410
static XSyncValue *pnext_time;
 
2411
 
 
2412
#define GetTime()\
 
2413
{\
 
2414
    unsigned long millis = GetTimeInMillis();\
 
2415
    unsigned long maxis = XSyncValueHigh32(Now);\
 
2416
    if (millis < XSyncValueLow32(Now)) maxis++;\
 
2417
    XSyncIntsToValue(&Now, millis, maxis);\
 
2418
}
 
2419
 
 
2420
/*
 
2421
*** Server Block Handler
 
2422
*** code inspired by multibuffer extension
 
2423
 */
 
2424
/*ARGSUSED*/
 
2425
static void ServertimeBlockHandler(env, wt, LastSelectMask)
 
2426
pointer env;
 
2427
struct timeval **wt;
 
2428
pointer LastSelectMask;
 
2429
{
 
2430
    XSyncValue delay;
 
2431
    unsigned long timeout;
 
2432
 
 
2433
    if (pnext_time)
 
2434
    {
 
2435
        GetTime();
 
2436
 
 
2437
        if (XSyncValueGreaterOrEqual(Now, *pnext_time))
 
2438
        {
 
2439
            timeout = 0;
 
2440
        } 
 
2441
        else
 
2442
        {
 
2443
            Bool overflow;
 
2444
            XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
 
2445
            (void)overflow;
 
2446
            timeout = XSyncValueLow32(delay);
 
2447
        }
 
2448
        AdjustWaitForDelay(wt, timeout); /* os/utils.c */
 
2449
    }
 
2450
}
 
2451
 
 
2452
/*
 
2453
*** Wakeup Handler
 
2454
 */
 
2455
/*ARGSUSED*/
 
2456
static void ServertimeWakeupHandler(env, rc, LastSelectMask)
 
2457
pointer env;
 
2458
int rc;
 
2459
pointer LastSelectMask;
 
2460
{
 
2461
    if (pnext_time)
 
2462
    {
 
2463
        GetTime();
 
2464
 
 
2465
        if (XSyncValueGreaterOrEqual(Now, *pnext_time))
 
2466
        {
 
2467
            SyncChangeCounter(ServertimeCounter, Now);
 
2468
        }
 
2469
    }
 
2470
}
 
2471
 
 
2472
static void
 
2473
ServertimeQueryValue(pCounter, pValue_return)
 
2474
    pointer pCounter;
 
2475
    CARD64 *pValue_return;
 
2476
{
 
2477
    GetTime();
 
2478
    *pValue_return = Now;
 
2479
}
 
2480
 
 
2481
static void
 
2482
ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater)
 
2483
    pointer pCounter;
 
2484
    CARD64 *pbracket_less;
 
2485
    CARD64 *pbracket_greater;
 
2486
{
 
2487
    if (!pnext_time && pbracket_greater)
 
2488
    {
 
2489
        RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
 
2490
                                       ServertimeWakeupHandler,
 
2491
                                       NULL);
 
2492
    }
 
2493
    else if (pnext_time && !pbracket_greater)
 
2494
    {
 
2495
        RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
 
2496
                                     ServertimeWakeupHandler,
 
2497
                                     NULL);
 
2498
    }
 
2499
    pnext_time = pbracket_greater;
 
2500
}
 
2501
 
 
2502
static void
 
2503
SyncInitServerTime()
 
2504
{
 
2505
    CARD64 resolution;
 
2506
 
 
2507
    XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
 
2508
    XSyncIntToValue(&resolution, 4);
 
2509
    ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
 
2510
                            XSyncCounterNeverDecreases,
 
2511
                            ServertimeQueryValue, ServertimeBracketValues);
 
2512
    pnext_time = NULL;
 
2513
}