]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_time.c
xnu-792.17.14.tar.gz
[apple/xnu.git] / bsd / kern / kern_time.c
CommitLineData
1c79356b 1/*
8f6c56a5 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
5d5c5d0d 3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29/*
30 * Copyright (c) 1982, 1986, 1989, 1993
31 * The Regents of the University of California. All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95
62 */
63
64#include <sys/param.h>
65#include <sys/resourcevar.h>
66#include <sys/kernel.h>
67#include <sys/systm.h>
91447636
A
68#include <sys/proc_internal.h>
69#include <sys/kauth.h>
1c79356b
A
70#include <sys/vnode.h>
71
91447636
A
72#include <sys/mount_internal.h>
73#include <sys/sysproto.h>
74#include <sys/signalvar.h>
1c79356b 75
1c79356b 76#include <kern/clock.h>
91447636 77#include <kern/thread_call.h>
1c79356b
A
78
79#define HZ 100 /* XXX */
80
9bccf70c 81/* simple lock used to access timezone, tz structure */
91447636
A
82lck_spin_t * tz_slock;
83lck_grp_t * tz_slock_grp;
84lck_attr_t * tz_slock_attr;
85lck_grp_attr_t *tz_slock_grp_attr;
86
87static void setthetime(
88 struct timeval *tv);
89
90void time_zone_slock_init(void);
91
8f6c56a5
A
92int gettimeofday(struct proc *p,
93#ifdef __ppc__
94 struct ppc_gettimeofday_args *uap,
95#else
96 struct gettimeofday_args *uap,
97#endif
98 register_t *retval);
99
1c79356b
A
100/*
101 * Time of day and interval timer support.
102 *
103 * These routines provide the kernel entry points to get and set
104 * the time-of-day and per-process interval timers. Subroutines
105 * here provide support for adding and subtracting timeval structures
106 * and decrementing interval timers, optionally reloading the interval
107 * timers when they expire.
8f6c56a5
A
108 *
109 * XXX Y2038 bug because of clock_get_calendar_microtime() first argument
1c79356b 110 */
1c79356b
A
111/* ARGSUSED */
112int
8f6c56a5
A
113gettimeofday(__unused struct proc *p,
114#ifdef __ppc__
115 register struct ppc_gettimeofday_args *uap,
116#else
117 register struct gettimeofday_args *uap,
118#endif
119 __unused register_t *retval)
1c79356b 120{
8f6c56a5 121 struct timeval atv;
1c79356b 122 int error = 0;
9bccf70c
A
123 struct timezone ltz; /* local copy */
124
8f6c56a5
A
125/* NOTE THIS implementation is for non ppc architectures only */
126
127 if (uap->tp) {
128 clock_get_calendar_microtime((uint32_t *)&atv.tv_sec, &atv.tv_usec);
129 if (IS_64BIT_PROCESS(p)) {
130 struct user_timeval user_atv;
131 user_atv.tv_sec = atv.tv_sec;
132 user_atv.tv_usec = atv.tv_usec;
133 /*
134 * This cast is not necessary for PPC, but is
135 * mostly harmless.
136 */
137 error = copyout(&user_atv, CAST_USER_ADDR_T(uap->tp), sizeof(struct user_timeval));
138 } else {
139 error = copyout(&atv, CAST_USER_ADDR_T(uap->tp), sizeof(struct timeval));
140 }
141 if (error)
142 return(error);
143 }
1c79356b 144
9bccf70c 145 if (uap->tzp) {
91447636 146 lck_spin_lock(tz_slock);
9bccf70c 147 ltz = tz;
91447636 148 lck_spin_unlock(tz_slock);
8f6c56a5
A
149 error = copyout((caddr_t)&ltz, CAST_USER_ADDR_T(uap->tzp),
150 sizeof (tz));
9bccf70c 151 }
1c79356b 152
8f6c56a5 153 return(error);
1c79356b
A
154}
155
91447636
A
156/*
157 * XXX Y2038 bug because of setthetime() argument
158 */
1c79356b
A
159/* ARGSUSED */
160int
91447636 161settimeofday(struct proc *p, struct settimeofday_args *uap, __unused register_t *retval)
1c79356b
A
162{
163 struct timeval atv;
164 struct timezone atz;
91447636 165 int error;
1c79356b 166
91447636 167 if ((error = suser(kauth_cred_get(), &p->p_acflag)))
1c79356b 168 return (error);
91447636
A
169 /* Verify all parameters before changing time */
170 if (uap->tv) {
171 if (IS_64BIT_PROCESS(p)) {
172 struct user_timeval user_atv;
173 error = copyin(uap->tv, &user_atv, sizeof(struct user_timeval));
174 atv.tv_sec = user_atv.tv_sec;
175 atv.tv_usec = user_atv.tv_usec;
176 } else {
177 error = copyin(uap->tv, &atv, sizeof(struct timeval));
178 }
179 if (error)
180 return (error);
181 }
182 if (uap->tzp && (error = copyin(uap->tzp, (caddr_t)&atz, sizeof(atz))))
1c79356b 183 return (error);
91447636
A
184 if (uap->tv) {
185 timevalfix(&atv);
186 if (atv.tv_sec < 0 || (atv.tv_sec == 0 && atv.tv_usec < 0))
187 return (EPERM);
1c79356b 188 setthetime(&atv);
91447636 189 }
9bccf70c 190 if (uap->tzp) {
91447636 191 lck_spin_lock(tz_slock);
1c79356b 192 tz = atz;
91447636 193 lck_spin_unlock(tz_slock);
9bccf70c 194 }
1c79356b
A
195 return (0);
196}
197
91447636
A
198static void
199setthetime(
200 struct timeval *tv)
1c79356b 201{
55e303ae 202 clock_set_calendar_microtime(tv->tv_sec, tv->tv_usec);
1c79356b
A
203}
204
91447636
A
205/*
206 * XXX Y2038 bug because of clock_adjtime() first argument
207 */
1c79356b
A
208/* ARGSUSED */
209int
91447636 210adjtime(struct proc *p, register struct adjtime_args *uap, __unused register_t *retval)
1c79356b 211{
9bccf70c 212 struct timeval atv;
9bccf70c 213 int error;
1c79356b 214
91447636 215 if ((error = suser(kauth_cred_get(), &p->p_acflag)))
1c79356b 216 return (error);
91447636
A
217 if (IS_64BIT_PROCESS(p)) {
218 struct user_timeval user_atv;
219 error = copyin(uap->delta, &user_atv, sizeof(struct user_timeval));
220 atv.tv_sec = user_atv.tv_sec;
221 atv.tv_usec = user_atv.tv_usec;
222 } else {
223 error = copyin(uap->delta, &atv, sizeof(struct timeval));
224 }
225 if (error)
9bccf70c 226 return (error);
1c79356b 227
91447636
A
228 /*
229 * Compute the total correction and the rate at which to apply it.
230 */
231 clock_adjtime((int32_t *)&atv.tv_sec, &atv.tv_usec);
1c79356b 232
1c79356b 233 if (uap->olddelta) {
91447636
A
234 if (IS_64BIT_PROCESS(p)) {
235 struct user_timeval user_atv;
236 user_atv.tv_sec = atv.tv_sec;
237 user_atv.tv_usec = atv.tv_usec;
238 error = copyout(&user_atv, uap->olddelta, sizeof(struct user_timeval));
239 } else {
240 error = copyout(&atv, uap->olddelta, sizeof(struct timeval));
241 }
1c79356b 242 }
1c79356b 243
9bccf70c 244 return (0);
1c79356b
A
245}
246
1c79356b 247/*
91447636
A
248 * Verify the calendar value. If negative,
249 * reset to zero (the epoch).
1c79356b
A
250 */
251void
91447636
A
252inittodr(
253 __unused time_t base)
1c79356b 254{
55e303ae
A
255 struct timeval tv;
256
1c79356b 257 /*
0b4e3aa0
A
258 * Assertion:
259 * The calendar has already been
91447636 260 * set up from the platform clock.
0b4e3aa0 261 *
1c79356b
A
262 * The value returned by microtime()
263 * is gotten from the calendar.
264 */
55e303ae 265 microtime(&tv);
1c79356b 266
91447636 267 if (tv.tv_sec < 0 || tv.tv_usec < 0) {
1c79356b 268 printf ("WARNING: preposterous time in Real Time Clock");
91447636
A
269 tv.tv_sec = 0; /* the UNIX epoch */
270 tv.tv_usec = 0;
271 setthetime(&tv);
1c79356b
A
272 printf(" -- CHECK AND RESET THE DATE!\n");
273 }
1c79356b
A
274}
275
91447636
A
276time_t
277boottime_sec(void)
278{
279 uint32_t sec, nanosec;
280 clock_get_boottime_nanotime(&sec, &nanosec);
281 return (sec);
282}
9bccf70c 283
91447636 284uint64_t tvtoabstime(struct timeval *tvp);
9bccf70c 285
1c79356b
A
286/*
287 * Get value of an interval timer. The process virtual and
9bccf70c 288 * profiling virtual time timers are kept internally in the
1c79356b
A
289 * way they are specified externally: in time until they expire.
290 *
9bccf70c
A
291 * The real time interval timer expiration time (p_rtime)
292 * is kept as an absolute time rather than as a delta, so that
293 * it is easy to keep periodic real-time signals from drifting.
1c79356b
A
294 *
295 * Virtual time timers are processed in the hardclock() routine of
9bccf70c
A
296 * kern_clock.c. The real time timer is processed by a callout
297 * routine. Since a callout may be delayed in real time due to
298 * other processing in the system, it is possible for the real
299 * time callout routine (realitexpire, given below), to be delayed
300 * in real time past when it is supposed to occur. It does not
301 * suffice, therefore, to reload the real time .it_value from the
302 * real time .it_interval. Rather, we compute the next time in
303 * absolute time when the timer should go off.
1c79356b
A
304 */
305
1c79356b
A
306/* ARGSUSED */
307int
91447636 308getitimer(struct proc *p, register struct getitimer_args *uap, __unused register_t *retval)
1c79356b
A
309{
310 struct itimerval aitv;
1c79356b
A
311
312 if (uap->which > ITIMER_PROF)
313 return(EINVAL);
1c79356b
A
314 if (uap->which == ITIMER_REAL) {
315 /*
9bccf70c
A
316 * If time for real time timer has passed return 0,
317 * else return difference between current time and
318 * time for the timer to go off.
1c79356b
A
319 */
320 aitv = p->p_realtimer;
9bccf70c
A
321 if (timerisset(&p->p_rtime)) {
322 struct timeval now;
323
324 microuptime(&now);
325 if (timercmp(&p->p_rtime, &now, <))
1c79356b 326 timerclear(&aitv.it_value);
9bccf70c
A
327 else {
328 aitv.it_value = p->p_rtime;
329 timevalsub(&aitv.it_value, &now);
330 }
331 }
332 else
333 timerclear(&aitv.it_value);
334 }
335 else
336 aitv = p->p_stats->p_timer[uap->which];
337
91447636
A
338 if (IS_64BIT_PROCESS(p)) {
339 struct user_itimerval user_itv;
340 user_itv.it_interval.tv_sec = aitv.it_interval.tv_sec;
341 user_itv.it_interval.tv_usec = aitv.it_interval.tv_usec;
342 user_itv.it_value.tv_sec = aitv.it_value.tv_sec;
343 user_itv.it_value.tv_usec = aitv.it_value.tv_usec;
344 return (copyout((caddr_t)&user_itv, uap->itv, sizeof (struct user_itimerval)));
345 } else {
346 return (copyout((caddr_t)&aitv, uap->itv, sizeof (struct itimerval)));
347 }
1c79356b
A
348}
349
1c79356b
A
350/* ARGSUSED */
351int
352setitimer(p, uap, retval)
353 struct proc *p;
354 register struct setitimer_args *uap;
355 register_t *retval;
356{
357 struct itimerval aitv;
91447636 358 user_addr_t itvp;
9bccf70c 359 int error;
1c79356b
A
360
361 if (uap->which > ITIMER_PROF)
9bccf70c 362 return (EINVAL);
91447636
A
363 if ((itvp = uap->itv)) {
364 if (IS_64BIT_PROCESS(p)) {
365 struct user_itimerval user_itv;
366 if ((error = copyin(itvp, (caddr_t)&user_itv, sizeof (struct user_itimerval))))
367 return (error);
368 aitv.it_interval.tv_sec = user_itv.it_interval.tv_sec;
369 aitv.it_interval.tv_usec = user_itv.it_interval.tv_usec;
370 aitv.it_value.tv_sec = user_itv.it_value.tv_sec;
371 aitv.it_value.tv_usec = user_itv.it_value.tv_usec;
372 } else {
373 if ((error = copyin(itvp, (caddr_t)&aitv, sizeof (struct itimerval))))
374 return (error);
375 }
376 }
377 if ((uap->itv = uap->oitv) && (error = getitimer(p, (struct getitimer_args *)uap, retval)))
1c79356b
A
378 return (error);
379 if (itvp == 0)
380 return (0);
381 if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
382 return (EINVAL);
1c79356b 383 if (uap->which == ITIMER_REAL) {
91447636 384 thread_call_func_cancel((thread_call_func_t)realitexpire, (void *)p->p_pid, FALSE);
1c79356b 385 if (timerisset(&aitv.it_value)) {
9bccf70c
A
386 microuptime(&p->p_rtime);
387 timevaladd(&p->p_rtime, &aitv.it_value);
388 thread_call_func_delayed(
91447636 389 (thread_call_func_t)realitexpire, (void *)p->p_pid,
9bccf70c 390 tvtoabstime(&p->p_rtime));
1c79356b 391 }
9bccf70c
A
392 else
393 timerclear(&p->p_rtime);
394
1c79356b 395 p->p_realtimer = aitv;
9bccf70c
A
396 }
397 else
1c79356b 398 p->p_stats->p_timer[uap->which] = aitv;
9bccf70c
A
399
400 return (0);
1c79356b
A
401}
402
403/*
404 * Real interval timer expired:
405 * send process whose timer expired an alarm signal.
406 * If time is not set up to reload, then just return.
407 * Else compute next time timer should go off which is > current time.
408 * This is where delay in processing this timeout causes multiple
409 * SIGALRM calls to be compressed into one.
410 */
411void
9bccf70c
A
412realitexpire(
413 void *pid)
1c79356b
A
414{
415 register struct proc *p;
9bccf70c 416 struct timeval now;
91447636 417 boolean_t funnel_state;
1c79356b 418
91447636 419 funnel_state = thread_funnel_set(kernel_flock, TRUE);
9bccf70c
A
420 p = pfind((pid_t)pid);
421 if (p == NULL) {
422 (void) thread_funnel_set(kernel_flock, FALSE);
1c79356b
A
423 return;
424 }
9bccf70c
A
425
426 if (!timerisset(&p->p_realtimer.it_interval)) {
427 timerclear(&p->p_rtime);
428 psignal(p, SIGALRM);
429
430 (void) thread_funnel_set(kernel_flock, FALSE);
1c79356b 431 return;
1c79356b 432 }
9bccf70c
A
433
434 microuptime(&now);
435 timevaladd(&p->p_rtime, &p->p_realtimer.it_interval);
436 if (timercmp(&p->p_rtime, &now, <=)) {
437 if ((p->p_rtime.tv_sec + 2) >= now.tv_sec) {
438 for (;;) {
439 timevaladd(&p->p_rtime, &p->p_realtimer.it_interval);
440 if (timercmp(&p->p_rtime, &now, >))
441 break;
442 }
443 }
444 else {
445 p->p_rtime = p->p_realtimer.it_interval;
446 timevaladd(&p->p_rtime, &now);
1c79356b 447 }
1c79356b 448 }
9bccf70c 449
9bccf70c
A
450 psignal(p, SIGALRM);
451
91447636 452 thread_call_func_delayed((thread_call_func_t)realitexpire, pid, tvtoabstime(&p->p_rtime));
55e303ae 453
1c79356b
A
454 (void) thread_funnel_set(kernel_flock, FALSE);
455}
456
457/*
458 * Check that a proposed value to load into the .it_value or
459 * .it_interval part of an interval timer is acceptable, and
460 * fix it to have at least minimal value (i.e. if it is less
461 * than the resolution of the clock, round it up.)
462 */
463int
464itimerfix(tv)
465 struct timeval *tv;
466{
467
468 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
469 tv->tv_usec < 0 || tv->tv_usec >= 1000000)
470 return (EINVAL);
471 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
472 tv->tv_usec = tick;
473 return (0);
474}
475
476/*
477 * Decrement an interval timer by a specified number
478 * of microseconds, which must be less than a second,
479 * i.e. < 1000000. If the timer expires, then reload
480 * it. In this case, carry over (usec - old value) to
481 * reducint the value reloaded into the timer so that
482 * the timer does not drift. This routine assumes
483 * that it is called in a context where the timers
484 * on which it is operating cannot change in value.
485 */
486int
487itimerdecr(itp, usec)
488 register struct itimerval *itp;
489 int usec;
490{
491
492 if (itp->it_value.tv_usec < usec) {
493 if (itp->it_value.tv_sec == 0) {
494 /* expired, and already in next interval */
495 usec -= itp->it_value.tv_usec;
496 goto expire;
497 }
498 itp->it_value.tv_usec += 1000000;
499 itp->it_value.tv_sec--;
500 }
501 itp->it_value.tv_usec -= usec;
502 usec = 0;
503 if (timerisset(&itp->it_value))
504 return (1);
505 /* expired, exactly at end of interval */
506expire:
507 if (timerisset(&itp->it_interval)) {
508 itp->it_value = itp->it_interval;
509 itp->it_value.tv_usec -= usec;
510 if (itp->it_value.tv_usec < 0) {
511 itp->it_value.tv_usec += 1000000;
512 itp->it_value.tv_sec--;
513 }
514 } else
515 itp->it_value.tv_usec = 0; /* sec is already 0 */
516 return (0);
517}
518
519/*
520 * Add and subtract routines for timevals.
521 * N.B.: subtract routine doesn't deal with
522 * results which are before the beginning,
523 * it just gets very confused in this case.
524 * Caveat emptor.
525 */
526void
9bccf70c
A
527timevaladd(
528 struct timeval *t1,
529 struct timeval *t2)
1c79356b
A
530{
531
532 t1->tv_sec += t2->tv_sec;
533 t1->tv_usec += t2->tv_usec;
534 timevalfix(t1);
535}
536void
9bccf70c
A
537timevalsub(
538 struct timeval *t1,
539 struct timeval *t2)
1c79356b
A
540{
541
542 t1->tv_sec -= t2->tv_sec;
543 t1->tv_usec -= t2->tv_usec;
544 timevalfix(t1);
545}
546void
9bccf70c
A
547timevalfix(
548 struct timeval *t1)
1c79356b
A
549{
550
551 if (t1->tv_usec < 0) {
552 t1->tv_sec--;
553 t1->tv_usec += 1000000;
554 }
555 if (t1->tv_usec >= 1000000) {
556 t1->tv_sec++;
557 t1->tv_usec -= 1000000;
558 }
559}
560
561/*
562 * Return the best possible estimate of the time in the timeval
563 * to which tvp points.
564 */
565void
9bccf70c
A
566microtime(
567 struct timeval *tvp)
1c79356b 568{
91447636 569 clock_get_calendar_microtime((uint32_t *)&tvp->tv_sec, &tvp->tv_usec);
1c79356b 570}
9bccf70c
A
571
572void
573microuptime(
574 struct timeval *tvp)
575{
91447636 576 clock_get_system_microtime((uint32_t *)&tvp->tv_sec, &tvp->tv_usec);
9bccf70c
A
577}
578
579/*
580 * Ditto for timespec.
581 */
582void
583nanotime(
584 struct timespec *tsp)
585{
91447636 586 clock_get_calendar_nanotime((uint32_t *)&tsp->tv_sec, (uint32_t *)&tsp->tv_nsec);
9bccf70c
A
587}
588
589void
590nanouptime(
591 struct timespec *tsp)
592{
91447636 593 clock_get_system_nanotime((uint32_t *)&tsp->tv_sec, (uint32_t *)&tsp->tv_nsec);
9bccf70c
A
594}
595
596uint64_t
597tvtoabstime(
598 struct timeval *tvp)
599{
600 uint64_t result, usresult;
601
602 clock_interval_to_absolutetime_interval(
603 tvp->tv_sec, NSEC_PER_SEC, &result);
604 clock_interval_to_absolutetime_interval(
605 tvp->tv_usec, NSEC_PER_USEC, &usresult);
606
607 return (result + usresult);
608}
609void
610time_zone_slock_init(void)
611{
91447636
A
612 /* allocate lock group attribute and group */
613 tz_slock_grp_attr = lck_grp_attr_alloc_init();
8f6c56a5 614 lck_grp_attr_setstat(tz_slock_grp_attr);
9bccf70c 615
91447636 616 tz_slock_grp = lck_grp_alloc_init("tzlock", tz_slock_grp_attr);
9bccf70c 617
91447636
A
618 /* Allocate lock attribute */
619 tz_slock_attr = lck_attr_alloc_init();
8f6c56a5 620 //lck_attr_setdebug(tz_slock_attr);
9bccf70c 621
91447636
A
622 /* Allocate the spin lock */
623 tz_slock = lck_spin_alloc_init(tz_slock_grp, tz_slock_attr);
9bccf70c 624}
91447636 625