1/* 2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 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 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 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 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 65 * support for mandatory and extensible security protections. This notice 66 * is included in support of clause 2.2 (b) of the Apple Public License, 67 * Version 2.0. 68 */ 69 70#include <sys/param.h> 71#include <sys/resourcevar.h> 72#include <sys/kernel.h> 73#include <sys/systm.h> 74#include <sys/proc_internal.h> 75#include <sys/kauth.h> 76#include <sys/vnode.h> 77#include <sys/time.h> 78#include <sys/priv.h> 79 80#include <sys/mount_internal.h> 81#include <sys/sysproto.h> 82#include <sys/signalvar.h> 83 84#include <kern/clock.h> 85#include <kern/task.h> 86#include <kern/thread_call.h> 87#if CONFIG_MACF 88#include <security/mac_framework.h> 89#endif 90 91#define HZ 100 /* XXX */ 92 93/* simple lock used to access timezone, tz structure */ 94lck_spin_t * tz_slock; 95lck_grp_t * tz_slock_grp; 96lck_attr_t * tz_slock_attr; 97lck_grp_attr_t *tz_slock_grp_attr; 98 99static void setthetime( 100 struct timeval *tv); 101 102void time_zone_slock_init(void) __attribute__((section("__TEXT, initcode"))); 103 104/* 105 * Time of day and interval timer support. 106 * 107 * These routines provide the kernel entry points to get and set 108 * the time-of-day and per-process interval timers. Subroutines 109 * here provide support for adding and subtracting timeval structures 110 * and decrementing interval timers, optionally reloading the interval 111 * timers when they expire. 112 */ 113/* ARGSUSED */ 114int 115gettimeofday( 116__unused struct proc *p, 117 struct gettimeofday_args *uap, 118 int32_t *retval) 119{ 120 int error = 0; 121 struct timezone ltz; /* local copy */ 122 123 if (uap->tp) { 124 clock_sec_t secs; 125 clock_usec_t usecs; 126 127 clock_gettimeofday(&secs, &usecs); 128 retval[0] = secs; 129 retval[1] = usecs; 130 } 131 132 if (uap->tzp) { 133 lck_spin_lock(tz_slock); 134 ltz = tz; 135 lck_spin_unlock(tz_slock); 136 137 error = copyout((caddr_t)<z, CAST_USER_ADDR_T(uap->tzp), sizeof (tz)); 138 } 139 140 return (error); 141} 142 143/* 144 * XXX Y2038 bug because of setthetime() argument 145 */ 146/* ARGSUSED */ 147int 148settimeofday(__unused struct proc *p, struct settimeofday_args *uap, __unused int32_t *retval) 149{ 150 struct timeval atv; 151 struct timezone atz; 152 int error; 153 154 bzero(&atv, sizeof(atv)); 155 156#if CONFIG_MACF 157 error = mac_system_check_settime(kauth_cred_get()); 158 if (error) 159 return (error); 160#endif 161#ifndef CONFIG_EMBEDDED 162 if ((error = suser(kauth_cred_get(), &p->p_acflag))) 163 return (error); 164#endif 165 /* Verify all parameters before changing time */ 166 if (uap->tv) { 167 if (IS_64BIT_PROCESS(p)) { 168 struct user64_timeval user_atv; 169 error = copyin(uap->tv, &user_atv, sizeof(user_atv)); 170 atv.tv_sec = user_atv.tv_sec; 171 atv.tv_usec = user_atv.tv_usec; 172 } else { 173 struct user32_timeval user_atv; 174 error = copyin(uap->tv, &user_atv, sizeof(user_atv)); 175 atv.tv_sec = user_atv.tv_sec; 176 atv.tv_usec = user_atv.tv_usec; 177 } 178 if (error) 179 return (error); 180 } 181 if (uap->tzp && (error = copyin(uap->tzp, (caddr_t)&atz, sizeof(atz)))) 182 return (error); 183 if (uap->tv) { 184 timevalfix(&atv); 185 if (atv.tv_sec < 0 || (atv.tv_sec == 0 && atv.tv_usec < 0)) 186 return (EPERM); 187 setthetime(&atv); 188 } 189 if (uap->tzp) { 190 lck_spin_lock(tz_slock); 191 tz = atz; 192 lck_spin_unlock(tz_slock); 193 } 194 return (0); 195} 196 197static void 198setthetime( 199 struct timeval *tv) 200{ 201 clock_set_calendar_microtime(tv->tv_sec, tv->tv_usec); 202} 203 204/* 205 * XXX Y2038 bug because of clock_adjtime() first argument 206 */ 207/* ARGSUSED */ 208int 209adjtime(struct proc *p, struct adjtime_args *uap, __unused int32_t *retval) 210{ 211 struct timeval atv; 212 int error; 213 214#if CONFIG_MACF 215 error = mac_system_check_settime(kauth_cred_get()); 216 if (error) 217 return (error); 218#endif 219 if ((error = priv_check_cred(kauth_cred_get(), PRIV_ADJTIME, 0))) 220 return (error); 221 if (IS_64BIT_PROCESS(p)) { 222 struct user64_timeval user_atv; 223 error = copyin(uap->delta, &user_atv, sizeof(user_atv)); 224 atv.tv_sec = user_atv.tv_sec; 225 atv.tv_usec = user_atv.tv_usec; 226 } else { 227 struct user32_timeval user_atv; 228 error = copyin(uap->delta, &user_atv, sizeof(user_atv)); 229 atv.tv_sec = user_atv.tv_sec; 230 atv.tv_usec = user_atv.tv_usec; 231 } 232 if (error) 233 return (error); 234 235 /* 236 * Compute the total correction and the rate at which to apply it. 237 */ 238 clock_adjtime(&atv.tv_sec, &atv.tv_usec); 239 240 if (uap->olddelta) { 241 if (IS_64BIT_PROCESS(p)) { 242 struct user64_timeval user_atv; 243 user_atv.tv_sec = atv.tv_sec; 244 user_atv.tv_usec = atv.tv_usec; 245 error = copyout(&user_atv, uap->olddelta, sizeof(user_atv)); 246 } else { 247 struct user32_timeval user_atv; 248 user_atv.tv_sec = atv.tv_sec; 249 user_atv.tv_usec = atv.tv_usec; 250 error = copyout(&user_atv, uap->olddelta, sizeof(user_atv)); 251 } 252 } 253 254 return (0); 255} 256 257/* 258 * Verify the calendar value. If negative, 259 * reset to zero (the epoch). 260 */ 261void 262inittodr( 263 __unused time_t base) 264{ 265 struct timeval tv; 266 267 /* 268 * Assertion: 269 * The calendar has already been 270 * set up from the platform clock. 271 * 272 * The value returned by microtime() 273 * is gotten from the calendar. 274 */ 275 microtime(&tv); 276 277 if (tv.tv_sec < 0 || tv.tv_usec < 0) { 278 printf ("WARNING: preposterous time in Real Time Clock"); 279 tv.tv_sec = 0; /* the UNIX epoch */ 280 tv.tv_usec = 0; 281 setthetime(&tv); 282 printf(" -- CHECK AND RESET THE DATE!\n"); 283 } 284} 285 286time_t 287boottime_sec(void) 288{ 289 clock_sec_t secs; 290 clock_nsec_t nanosecs; 291 292 clock_get_boottime_nanotime(&secs, &nanosecs); 293 return (secs); 294} 295 296/* 297 * Get value of an interval timer. The process virtual and 298 * profiling virtual time timers are kept internally in the 299 * way they are specified externally: in time until they expire. 300 * 301 * The real time interval timer expiration time (p_rtime) 302 * is kept as an absolute time rather than as a delta, so that 303 * it is easy to keep periodic real-time signals from drifting. 304 * 305 * The real time timer is processed by a callout routine. 306 * Since a callout may be delayed in real time due to 307 * other processing in the system, it is possible for the real 308 * time callout routine (realitexpire, given below), to be delayed 309 * in real time past when it is supposed to occur. It does not 310 * suffice, therefore, to reload the real time .it_value from the 311 * real time .it_interval. Rather, we compute the next time in 312 * absolute time when the timer should go off. 313 * 314 * Returns: 0 Success 315 * EINVAL Invalid argument 316 * copyout:EFAULT Bad address 317 */ 318/* ARGSUSED */ 319int 320getitimer(struct proc *p, struct getitimer_args *uap, __unused int32_t *retval) 321{ 322 struct itimerval aitv; 323 324 if (uap->which > ITIMER_PROF) 325 return(EINVAL); 326 327 bzero(&aitv, sizeof(aitv)); 328 329 proc_spinlock(p); 330 switch (uap->which) { 331 332 case ITIMER_REAL: 333 /* 334 * If time for real time timer has passed return 0, 335 * else return difference between current time and 336 * time for the timer to go off. 337 */ 338 aitv = p->p_realtimer; 339 if (timerisset(&p->p_rtime)) { 340 struct timeval now; 341 342 microuptime(&now); 343 if (timercmp(&p->p_rtime, &now, <)) 344 timerclear(&aitv.it_value); 345 else { 346 aitv.it_value = p->p_rtime; 347 timevalsub(&aitv.it_value, &now); 348 } 349 } 350 else 351 timerclear(&aitv.it_value); 352 break; 353 354 case ITIMER_VIRTUAL: 355 aitv = p->p_vtimer_user; 356 break; 357 358 case ITIMER_PROF: 359 aitv = p->p_vtimer_prof; 360 break; 361 } 362 363 proc_spinunlock(p); 364 365 if (IS_64BIT_PROCESS(p)) { 366 struct user64_itimerval user_itv; 367 user_itv.it_interval.tv_sec = aitv.it_interval.tv_sec; 368 user_itv.it_interval.tv_usec = aitv.it_interval.tv_usec; 369 user_itv.it_value.tv_sec = aitv.it_value.tv_sec; 370 user_itv.it_value.tv_usec = aitv.it_value.tv_usec; 371 return (copyout((caddr_t)&user_itv, uap->itv, sizeof (user_itv))); 372 } else { 373 struct user32_itimerval user_itv; 374 user_itv.it_interval.tv_sec = aitv.it_interval.tv_sec; 375 user_itv.it_interval.tv_usec = aitv.it_interval.tv_usec; 376 user_itv.it_value.tv_sec = aitv.it_value.tv_sec; 377 user_itv.it_value.tv_usec = aitv.it_value.tv_usec; 378 return (copyout((caddr_t)&user_itv, uap->itv, sizeof (user_itv))); 379 } 380} 381 382/* 383 * Returns: 0 Success 384 * EINVAL Invalid argument 385 * copyin:EFAULT Bad address 386 * getitimer:EINVAL Invalid argument 387 * getitimer:EFAULT Bad address 388 */ 389/* ARGSUSED */ 390int 391setitimer(struct proc *p, struct setitimer_args *uap, int32_t *retval) 392{ 393 struct itimerval aitv; 394 user_addr_t itvp; 395 int error; 396 397 bzero(&aitv, sizeof(aitv)); 398 399 if (uap->which > ITIMER_PROF) 400 return (EINVAL); 401 if ((itvp = uap->itv)) { 402 if (IS_64BIT_PROCESS(p)) { 403 struct user64_itimerval user_itv; 404 if ((error = copyin(itvp, (caddr_t)&user_itv, sizeof (user_itv)))) 405 return (error); 406 aitv.it_interval.tv_sec = user_itv.it_interval.tv_sec; 407 aitv.it_interval.tv_usec = user_itv.it_interval.tv_usec; 408 aitv.it_value.tv_sec = user_itv.it_value.tv_sec; 409 aitv.it_value.tv_usec = user_itv.it_value.tv_usec; 410 } else { 411 struct user32_itimerval user_itv; 412 if ((error = copyin(itvp, (caddr_t)&user_itv, sizeof (user_itv)))) 413 return (error); 414 aitv.it_interval.tv_sec = user_itv.it_interval.tv_sec; 415 aitv.it_interval.tv_usec = user_itv.it_interval.tv_usec; 416 aitv.it_value.tv_sec = user_itv.it_value.tv_sec; 417 aitv.it_value.tv_usec = user_itv.it_value.tv_usec; 418 } 419 } 420 if ((uap->itv = uap->oitv) && (error = getitimer(p, (struct getitimer_args *)uap, retval))) 421 return (error); 422 if (itvp == 0) 423 return (0); 424 if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) 425 return (EINVAL); 426 427 switch (uap->which) { 428 429 case ITIMER_REAL: 430 proc_spinlock(p); 431 if (timerisset(&aitv.it_value)) { 432 microuptime(&p->p_rtime); 433 timevaladd(&p->p_rtime, &aitv.it_value); 434 p->p_realtimer = aitv; 435 if (!thread_call_enter_delayed(p->p_rcall, tvtoabstime(&p->p_rtime))) 436 p->p_ractive++; 437 } else { 438 timerclear(&p->p_rtime); 439 p->p_realtimer = aitv; 440 if (thread_call_cancel(p->p_rcall)) 441 p->p_ractive--; 442 } 443 proc_spinunlock(p); 444 445 break; 446 447 448 case ITIMER_VIRTUAL: 449 if (timerisset(&aitv.it_value)) 450 task_vtimer_set(p->task, TASK_VTIMER_USER); 451 else 452 task_vtimer_clear(p->task, TASK_VTIMER_USER); 453 454 proc_spinlock(p); 455 p->p_vtimer_user = aitv; 456 proc_spinunlock(p); 457 break; 458 459 case ITIMER_PROF: 460 if (timerisset(&aitv.it_value)) 461 task_vtimer_set(p->task, TASK_VTIMER_PROF); 462 else 463 task_vtimer_clear(p->task, TASK_VTIMER_PROF); 464 465 proc_spinlock(p); 466 p->p_vtimer_prof = aitv; 467 proc_spinunlock(p); 468 break; 469 } 470 471 return (0); 472} 473 474/* 475 * Real interval timer expired: 476 * send process whose timer expired an alarm signal. 477 * If time is not set up to reload, then just return. 478 * Else compute next time timer should go off which is > current time. 479 * This is where delay in processing this timeout causes multiple 480 * SIGALRM calls to be compressed into one. 481 */ 482void 483realitexpire( 484 struct proc *p) 485{ 486 struct proc *r; 487 struct timeval t; 488 489 r = proc_find(p->p_pid); 490 491 proc_spinlock(p); 492 493 if (--p->p_ractive > 0 || r != p) { 494 proc_spinunlock(p); 495 496 if (r != NULL) 497 proc_rele(r); 498 return; 499 } 500 501 if (!timerisset(&p->p_realtimer.it_interval)) { 502 timerclear(&p->p_rtime); 503 proc_spinunlock(p); 504 505 psignal(p, SIGALRM); 506 proc_rele(p); 507 return; 508 } 509 510 microuptime(&t); 511 timevaladd(&p->p_rtime, &p->p_realtimer.it_interval); 512 if (timercmp(&p->p_rtime, &t, <=)) { 513 if ((p->p_rtime.tv_sec + 2) >= t.tv_sec) { 514 for (;;) { 515 timevaladd(&p->p_rtime, &p->p_realtimer.it_interval); 516 if (timercmp(&p->p_rtime, &t, >)) 517 break; 518 } 519 } 520 else { 521 p->p_rtime = p->p_realtimer.it_interval; 522 timevaladd(&p->p_rtime, &t); 523 } 524 } 525 526 if (!thread_call_enter_delayed(p->p_rcall, tvtoabstime(&p->p_rtime))) 527 p->p_ractive++; 528 proc_spinunlock(p); 529 530 psignal(p, SIGALRM); 531 proc_rele(p); 532} 533 534/* 535 * Check that a proposed value to load into the .it_value or 536 * .it_interval part of an interval timer is acceptable. 537 */ 538int 539itimerfix( 540 struct timeval *tv) 541{ 542 543 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 544 tv->tv_usec < 0 || tv->tv_usec >= 1000000) 545 return (EINVAL); 546 return (0); 547} 548 549/* 550 * Decrement an interval timer by a specified number 551 * of microseconds, which must be less than a second, 552 * i.e. < 1000000. If the timer expires, then reload 553 * it. In this case, carry over (usec - old value) to 554 * reduce the value reloaded into the timer so that 555 * the timer does not drift. This routine assumes 556 * that it is called in a context where the timers 557 * on which it is operating cannot change in value. 558 */ 559int 560itimerdecr(proc_t p, 561 struct itimerval *itp, int usec) 562{ 563 564 proc_spinlock(p); 565 566 if (itp->it_value.tv_usec < usec) { 567 if (itp->it_value.tv_sec == 0) { 568 /* expired, and already in next interval */ 569 usec -= itp->it_value.tv_usec; 570 goto expire; 571 } 572 itp->it_value.tv_usec += 1000000; 573 itp->it_value.tv_sec--; 574 } 575 itp->it_value.tv_usec -= usec; 576 usec = 0; 577 if (timerisset(&itp->it_value)) { 578 proc_spinunlock(p); 579 return (1); 580 } 581 /* expired, exactly at end of interval */ 582expire: 583 if (timerisset(&itp->it_interval)) { 584 itp->it_value = itp->it_interval; 585 if (itp->it_value.tv_sec > 0) { 586 itp->it_value.tv_usec -= usec; 587 if (itp->it_value.tv_usec < 0) { 588 itp->it_value.tv_usec += 1000000; 589 itp->it_value.tv_sec--; 590 } 591 } 592 } else 593 itp->it_value.tv_usec = 0; /* sec is already 0 */ 594 proc_spinunlock(p); 595 return (0); 596} 597 598/* 599 * Add and subtract routines for timevals. 600 * N.B.: subtract routine doesn't deal with 601 * results which are before the beginning, 602 * it just gets very confused in this case. 603 * Caveat emptor. 604 */ 605void 606timevaladd( 607 struct timeval *t1, 608 struct timeval *t2) 609{ 610 611 t1->tv_sec += t2->tv_sec; 612 t1->tv_usec += t2->tv_usec; 613 timevalfix(t1); 614} 615void 616timevalsub( 617 struct timeval *t1, 618 struct timeval *t2) 619{ 620 621 t1->tv_sec -= t2->tv_sec; 622 t1->tv_usec -= t2->tv_usec; 623 timevalfix(t1); 624} 625void 626timevalfix( 627 struct timeval *t1) 628{ 629 630 if (t1->tv_usec < 0) { 631 t1->tv_sec--; 632 t1->tv_usec += 1000000; 633 } 634 if (t1->tv_usec >= 1000000) { 635 t1->tv_sec++; 636 t1->tv_usec -= 1000000; 637 } 638} 639 640/* 641 * Return the best possible estimate of the time in the timeval 642 * to which tvp points. 643 */ 644void 645microtime( 646 struct timeval *tvp) 647{ 648 clock_sec_t tv_sec; 649 clock_usec_t tv_usec; 650 651 clock_get_calendar_microtime(&tv_sec, &tv_usec); 652 653 tvp->tv_sec = tv_sec; 654 tvp->tv_usec = tv_usec; 655} 656 657void 658microuptime( 659 struct timeval *tvp) 660{ 661 clock_sec_t tv_sec; 662 clock_usec_t tv_usec; 663 664 clock_get_system_microtime(&tv_sec, &tv_usec); 665 666 tvp->tv_sec = tv_sec; 667 tvp->tv_usec = tv_usec; 668} 669 670/* 671 * Ditto for timespec. 672 */ 673void 674nanotime( 675 struct timespec *tsp) 676{ 677 clock_sec_t tv_sec; 678 clock_nsec_t tv_nsec; 679 680 clock_get_calendar_nanotime(&tv_sec, &tv_nsec); 681 682 tsp->tv_sec = tv_sec; 683 tsp->tv_nsec = tv_nsec; 684} 685 686void 687nanouptime( 688 struct timespec *tsp) 689{ 690 clock_sec_t tv_sec; 691 clock_nsec_t tv_nsec; 692 693 clock_get_system_nanotime(&tv_sec, &tv_nsec); 694 695 tsp->tv_sec = tv_sec; 696 tsp->tv_nsec = tv_nsec; 697} 698 699uint64_t 700tvtoabstime( 701 struct timeval *tvp) 702{ 703 uint64_t result, usresult; 704 705 clock_interval_to_absolutetime_interval( 706 tvp->tv_sec, NSEC_PER_SEC, &result); 707 clock_interval_to_absolutetime_interval( 708 tvp->tv_usec, NSEC_PER_USEC, &usresult); 709 710 return (result + usresult); 711} 712void 713time_zone_slock_init(void) 714{ 715 /* allocate lock group attribute and group */ 716 tz_slock_grp_attr = lck_grp_attr_alloc_init(); 717 718 tz_slock_grp = lck_grp_alloc_init("tzlock", tz_slock_grp_attr); 719 720 /* Allocate lock attribute */ 721 tz_slock_attr = lck_attr_alloc_init(); 722 723 /* Allocate the spin lock */ 724 tz_slock = lck_spin_alloc_init(tz_slock_grp, tz_slock_attr); 725} 726