1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME 80** 81** perf.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Server manager routines for the perf interface of the performance and 90** system exerciser. 91** 92** 93*/ 94#include <stdlib.h> 95#include <string.h> 96#include <malloc.h> 97#include <unistd.h> 98#include <sys/file.h> 99#include <sys/fcntl.h> 100#include <sys/wait.h> 101#include <perf_c.h> 102#include <perf_p.h> 103 104void print_binding_info(char *text, handle_t h); 105 106static int n_calls = 0, 107 n_brd = 0, 108 n_maybe = 0, 109 n_brd_maybe = 0; 110 111static struct 112{ 113 unsigned32 count; 114 uuid_p_t uuid[3]; 115} object_vec = 116{ 117 3, 118 { 119 &NilObj, 120 &NilTypeObj, 121 (uuid_p_t) &FooObj1 122 } 123}; 124 125 126/***************************************************************************/ 127 128static void common() 129{ 130 n_calls++; 131} 132 133/***************************************************************************/ 134 135void perf_init 136( 137 handle_t h 138) 139{ 140 print_binding_info ("perf_init", h); 141 n_calls = 0; 142} 143 144/***************************************************************************/ 145 146void perf_info 147( 148 handle_t h __attribute__(unused), 149 unsigned32 *n, 150 unsigned32 *nm, 151 unsigned32 *nb, 152 unsigned32 *nbm 153) 154{ 155 *n = n_calls; 156 *nm = n_maybe; 157 *nb = n_brd; 158 *nbm = n_brd_maybe; 159} 160 161/***************************************************************************/ 162 163void perf_null 164( 165 handle_t h __attribute__(unused) 166) 167{ 168 common(); 169} 170 171/***************************************************************************/ 172 173void perf_null_idem 174( 175 handle_t h __attribute__(unused) 176) 177{ 178 common(); 179} 180 181/***************************************************************************/ 182 183void perf_in 184( 185 handle_t h __attribute__(unused), 186 perf_data_t d, 187 unsigned32 l, 188 idl_boolean verify, 189 unsigned32 *sum 190) 191{ 192 unsigned long i, rsum; 193 194 common(); 195 196 if (! verify) 197 { 198 return; 199 } 200 201 for (i = 0, rsum = 0; i < l; i++) 202 { 203 rsum += d[i]; 204 } 205 206 *sum = rsum; 207} 208 209/***************************************************************************/ 210 211void perf_in_idem 212( 213 handle_t h __attribute__(unused), 214 perf_data_t d, 215 unsigned32 l, 216 idl_boolean verify, 217 unsigned32 *sum 218) 219{ 220 perf_in(h, d, l, verify, sum); 221} 222 223/***************************************************************************/ 224 225void perf_out 226( 227 handle_t h __attribute__(unused), 228 perf_data_t d, 229 unsigned32 *l, 230 unsigned32 m, 231 unsigned32 pass, 232 idl_boolean verify 233) 234{ 235 unsigned long i; 236 237 common(); 238 239 if (! verify) 240 { 241 return; 242 } 243 244 for (i = 0; i < *l; i++) 245 { 246 d[i] = i * perf_magic * pass; 247 } 248 249 *l = m; 250} 251 252/***************************************************************************/ 253 254void perf_out_idem 255( 256 handle_t h, 257 perf_data_t d, 258 unsigned32 *l, 259 unsigned32 m, 260 unsigned32 pass, 261 idl_boolean verify 262) 263{ 264 perf_out(h, d, l, m, pass, verify); 265} 266 267/***************************************************************************/ 268 269void perf_brd 270( 271 handle_t h, 272 idl_char *name 273) 274{ 275 print_binding_info ("perf_brd", h); 276 common(); 277 n_brd++; 278 gethostname(name, 256); 279} 280 281/***************************************************************************/ 282 283void perf_maybe 284( 285 handle_t h 286) 287{ 288 print_binding_info ("perf_maybe", h); 289 common(); 290 n_maybe++; 291} 292 293/***************************************************************************/ 294 295void perf_brd_maybe 296( 297 handle_t h 298) 299{ 300 print_binding_info ("perf_brd_maybe", h); 301 common(); 302 n_brd_maybe++; 303} 304 305/***************************************************************************/ 306 307void perf_fp_test 308( 309 handle_t h __attribute__(unused), 310 float *f1, 311 float *f2, 312 double d1, 313 double d2, 314 float *o1, 315 double *o2 316) 317{ 318 common(); 319 320 UNMARSHALL_DOUBLE(d1); 321 UNMARSHALL_DOUBLE(d2); 322 323 *o1 = (*f1 / *f2) * (d1 / d2); 324 *o2 = (*f2 / *f1) * (d2 / d1); 325 326 MARSHALL_DOUBLE(*o2); 327} 328 329/***************************************************************************/ 330 331static boolean32 got_fwd_bindings = false; 332static rpc_binding_vector_p_t fwd_bv; 333 334void perf_register_b 335( 336 handle_t h, 337 idl_boolean global __attribute__(unused), 338 unsigned32 *st 339) 340{ 341 unsigned_char_p_t bstr; 342 unsigned_char_p_t protseq; 343 unsigned int i; 344 unsigned32 xst; 345 extern rpc_if_handle_t perfb_v1_0_s_ifspec; 346 extern perfb_v1_0_epv_t perfb_mgr_epv; 347 extern rpc_binding_vector_p_t bv; 348 349 print_binding_info ("perf_register_b", h); 350 351 if (! got_fwd_bindings) 352 { 353#ifndef REUSE_SERVER_BINDINGS 354 /* 355 * Create a new endpoint to receive the request on. Just use 356 * a single protseq; the first one in the server's binding list 357 * will do. 358 */ 359 360 rpc_binding_to_string_binding(bv->binding_h[0], &bstr, st); 361 rpc_string_binding_parse(bstr, NULL, &protseq, NULL, NULL, NULL, st); 362 rpc_server_use_protseq(protseq, 1, st); 363 if (*st != 0) 364 { 365 fprintf(stderr, "*** Can't use_protseq - %s\n", 366 error_text(*st)); 367 return; 368 } 369 rpc_string_free(&protseq, st); 370 rpc_string_free(&bstr, st); 371 372 /* 373 * Need to come up with a vector of handles to the newly created 374 * endpoint. This is a real hack (the ordering of the handles 375 * is presumptious), but it should work for the purposes of this 376 * test. The correct thing to do would be to convert all the bindings 377 * to binding-strings and filter out all duplicates. 378 */ 379 380 rpc_server_inq_bindings(&fwd_bv, st); 381 if (fwd_bv->count <= bv->count) 382 { 383 fprintf(stderr, "*** No additional bindings created for forwarding?\n"); 384 *st = -1; /* !!! */ 385 return; 386 } 387 388 /* 389 * Free all the pre-existing handles and shuffle the new ones to the 390 * beginning of the vector (adjust the count appropriately). 391 */ 392 393 for (i = 0; i < bv->count; i++) 394 rpc_binding_free(&fwd_bv->binding_h[i], st); 395 396 for (i = bv->count; i < fwd_bv->count; i++) 397 { 398 rpc_binding_copy(fwd_bv->binding_h[i], 399 &fwd_bv->binding_h[i-bv->count], st); 400 rpc_binding_free(&fwd_bv->binding_h[i], st); 401 } 402 fwd_bv->count = i - bv->count; 403#else 404 /* 405 * Just use the original bindings... this is slightly unorthodox 406 * (not going fully through the effort to duplicate the binding 407 * references) but it should work since neither the original nor 408 * the duplicate bindings are freed. 409 */ 410 fwd_bv = bv; 411#endif 412 printf("+ Got bindings:\n"); 413 for (i = 0; i < fwd_bv->count; i++) 414 { 415 rpc_binding_to_string_binding(fwd_bv->binding_h[i], &bstr, st); 416 printf(" %s\n", (char *)bstr); 417 rpc_string_free(&bstr, st); 418 } 419 got_fwd_bindings = true; 420 } 421 422 rpc_server_register_if(perfb_v1_0_s_ifspec, 423 (uuid_p_t) NULL, (rpc_mgr_epv_t) &perfb_mgr_epv, st); 424 if (*st != 0) 425 { 426 fprintf(stderr, "*** Can't rpc_server_register_if - %s\n", 427 error_text (*st)); 428 return; 429 } 430 431 rpc_ep_register(perfb_v1_0_s_ifspec, fwd_bv, (uuid_vector_p_t) &object_vec, 432 (unsigned_char_p_t)"perfb forwarding test manager", st); 433 434 if (*st != 0) 435 { 436 fprintf(stderr, "*** Can't rpc_ep_register - %s\n", 437 error_text (*st)); 438 rpc_server_unregister_if(perfb_v1_0_s_ifspec, (uuid_p_t) NULL, &xst); 439 if (xst != 0) 440 { 441 fprintf(stderr, "*** Can't rpc_server_unregister_if - %s\n", 442 error_text(xst)); 443 } 444 return; 445 } 446} 447 448/***************************************************************************/ 449 450void perf_unregister_b 451( 452 handle_t h, 453 unsigned32 *st 454) 455{ 456 unsigned32 st1, st2; 457 extern rpc_if_handle_t perfb_v1_0_s_ifspec; 458 459 print_binding_info ("perf_unregister_b", h); 460 461 if (!got_fwd_bindings) 462 { 463 fprintf(stderr, "*** perf_unregister_b - no fwd bindings\n"); 464 *st = -1; /* !!! */ 465 } 466 467 rpc_ep_unregister(perfb_v1_0_s_ifspec, fwd_bv, 468 (uuid_vector_p_t) &object_vec, &st1); 469 if (st1 != 0) 470 { 471 fprintf(stderr, "*** Can't rpc_ep_unregister - %s\n", 472 error_text (st1)); 473 } 474 475 rpc_server_unregister_if(perfb_v1_0_s_ifspec, (uuid_p_t) NULL, &st2); 476 if (st2 != 0) 477 { 478 fprintf(stderr, "*** Can't rpc_server_unregister_if - %s\n", 479 error_text(st2)); 480 } 481 482 *st = (st1 != 0) ? st1 : st2; 483} 484 485 486/***************************************************************************/ 487 488void perf_exception 489( 490 handle_t h 491) 492{ 493 494 print_binding_info ("perf_exception", h); 495 496 /* 497 * Here we raise an exception which the server stub will 498 * catch, and hopefully, bounce back to the client. 499 * 500 * At various times, this code did a floating point divide by 501 * zero, and a kill (self, SIGFPE). In the current DCE 1.0.2 502 * implementation, the threads package terminates the process 503 * upon synchronous terminating signals, and we cannot easily 504 * catch them. Therefore do a simple RAISE here. 505 */ 506 507 RAISE (exc_e_intdiv); 508 509} 510 511/***************************************************************************/ 512 513static void slow 514( 515 handle_t h __attribute__(unused), 516 perf_slow_mode_t mode, 517 unsigned32 secs 518) 519{ 520 long start_time; 521 522 common(); 523 524 TRY 525 { 526 start_time = time(0l); 527 528 switch ((int) mode) 529 { 530 case perf_slow_sleep: 531 printf("+ Sleeping for %lu seconds...\n", secs); 532 SLEEP(secs); 533 printf(" ...awake!\n"); 534 break; 535 536 case perf_slow_cpu: 537 printf("+ CPU looping for %lu seconds...\n", secs); 538 while ((unsigned32)(time(0) - start_time) < secs) 539 { 540 ; 541 } 542 printf(" ...done!\n"); 543 break; 544 545 case perf_slow_io: 546 { 547 char *heap = (char *) malloc(secs); 548 int f, n; 549 unsigned long i; 550 static char buf[] = "0123456789ABCDE\n"; 551 char *t; 552 char TempFileName [] = "/tmp/perfXXXXXX"; 553 554 t = (char *) mktemp(TempFileName); 555 printf("+ Writing file \"%s\" (size=%ld bytes)\n", t, secs); 556 f = open(t, (O_TRUNC | O_RDWR | O_CREAT), 0777); 557 if (f < 0) 558 { 559 perror("Can't create temp file"); 560 goto DONE; 561 } 562 563 for (i = 0; i < secs; i++) 564 { 565 n = write(f, buf, sizeof buf); 566 if (n != sizeof buf) 567 { 568 perror("Write failed"); 569 goto DONE; 570 } 571 } 572 for (i = 0; i < 10; i++) 573 { 574 lseek(f, 0L, 0); 575 n = read(f, heap, (int) secs); 576 if (n < 0) 577 { 578 perror("Read failed"); 579 goto DONE; 580 } 581 printf(" ...read %d bytes (%ld)\n", n, i); 582 } 583 584DONE: 585 printf(" ...done!\n"); 586 free(heap); 587 if (f >= 0) 588 close(f); 589 unlink(t); 590 break; 591 } 592 case perf_slow_fork_sleep: 593 { 594 pid_t cpid; 595 pid_t pid; 596 char buf[16]; 597 printf("+ Forking sleep for %lu seconds...\n", secs); 598 sprintf(buf, "%lu", secs); 599 cpid = fork(); 600 if (cpid == 0) 601 { 602 /* Child */ 603 execlp("sleep", "sleep", buf, 0); 604 } 605 else 606 { 607 /* Parent */ 608 /* 609 * CMA doesn't wrap waitpid()! 610 */ 611 pid = waitpid(cpid, NULL, WNOHANG); 612 if (pid != -1) 613 { 614 SLEEP(secs-1); 615 waitpid(cpid, NULL, 0); 616 } 617 } 618 printf(" ...awake!\n"); 619 break; 620 } 621 } 622 } 623 CATCH(cma_e_alerted) 624 { 625 printf(" ...'cancel' exception caught\n"); 626 RERAISE; 627 } 628 CATCH_ALL 629 { 630 printf(" ...unknown exception caught\n"); 631 RERAISE; 632 } 633 ENDTRY 634} 635 636/***************************************************************************/ 637 638void perf_null_slow 639( 640 handle_t h, 641 perf_slow_mode_t mode, 642 unsigned32 secs 643) 644{ 645 int oc = 0; 646 647 if (mode == perf_slow_cpu) 648 oc = pthread_setcancel(CANCEL_OFF); 649 650 print_binding_info ("perf_null_slow", h); 651 slow (h, mode, secs); 652 653 if (mode == perf_slow_cpu) 654 pthread_setcancel(oc); 655 656} 657 658/***************************************************************************/ 659 660void perf_null_slow_idem 661( 662 handle_t h, 663 perf_slow_mode_t mode, 664 unsigned32 secs 665) 666{ 667 int oc =0; 668 669 if (mode == perf_slow_cpu) 670 oc = pthread_setcancel(CANCEL_OFF); 671 672 print_binding_info ("perf_null_slow_idem", h); 673 slow(h, mode, secs); 674 675 if (mode == perf_slow_cpu) 676 pthread_setcancel(oc); 677 678} 679 680/***************************************************************************/ 681 682void perf_shutdown 683( 684 handle_t h 685) 686{ 687 unsigned32 st; 688 689 print_binding_info ("perf_shutdown", h); 690 common(); 691 rpc_mgmt_stop_server_listening (NULL, &st); 692} 693 694/***************************************************************************/ 695 696struct shutdown_info 697{ 698 unsigned32 secs; 699}; 700 701static void *shutdown_thread 702( 703 void *p_ 704) 705{ 706 struct shutdown_info *p = (struct shutdown_info *) p_; 707 unsigned32 st; 708 709 printf ("+ Shutdown thread...\n"); 710 711 printf (" sleeping for %lu seconds\n", p->secs); 712 SLEEP (p->secs); 713 714 if (use_reserved_threads) 715 { 716 printf (" unreserving threads (non blocking)...\n"); 717 teardown_thread_pools(false /* don't block */); 718 } 719 720 printf (" calling \"rpc_mgmt_stop_server_listening\"...\n"); 721 rpc_mgmt_stop_server_listening (NULL, &st); 722 723 free (p); 724 printf (" exiting thread\n"); 725 726 return NULL; 727} 728 729void perf_shutdown2 730( 731 handle_t h __attribute__(unused), 732 unsigned32 secs 733) 734{ 735 struct shutdown_info *p; 736 pthread_t thread; 737 738 common(); 739 740 printf ("+ Creating shutdown thread\n"); 741 742 p = (struct shutdown_info *) malloc (sizeof *p); 743 p->secs = secs; 744 745 pthread_create (&thread, pthread_attr_default, 746 shutdown_thread, (void *) p); 747 pthread_detach (&thread); 748} 749 750 751/***************************************************************************/ 752 753void perf_call_callback 754( 755 handle_t h, 756 unsigned32 idem 757) 758{ 759 unsigned i; 760 unsigned32 c, passes; 761 unsigned32 st; 762 763 print_binding_info ("perf_call_callback", h); 764 common(); 765 766 perfc_init(h, &passes); 767 768 for (i = 1; i <= passes; i++) 769 { 770 if (idem) 771 { 772 perfc_cb_idem(h, &c); 773 } 774 else 775 { 776 perfc_cb(h, &c); 777 } 778 } 779 780 if ((! idem) && c != passes) 781 { 782 printf(" ...count mismatch [%lu, %lu]\n", c, passes); 783 st = 1; 784#ifdef NOTDEF 785 pfm_$signal(st); 786#endif 787 } 788} 789 790/***************************************************************************/ 791 792struct context 793{ 794 unsigned long magic; 795 unsigned long data; 796}; 797 798#define CONTEXT_MAGIC 0xfeedf00d 799 800void perf_context_t_rundown 801( 802 rpc_ss_context_t context 803) 804{ 805 struct context *p = (struct context *) context; 806 807 printf("+ In context rundown function\n"); 808 809 if (p->magic != CONTEXT_MAGIC) 810 { 811 fprintf(stderr, "*** context mismatch; %08lx != %08x\n", p->magic, CONTEXT_MAGIC); 812 return; 813 } 814 815 free(context); 816} 817 818/***************************************************************************/ 819 820void perf_get_context 821( 822 handle_t h, 823 unsigned32 data, 824 perf_context_t *context 825) 826{ 827 struct context *p; 828 829 print_binding_info ("perf_get_context", h); 830 p = (struct context *) malloc(sizeof(struct context)); 831 832 p->magic = CONTEXT_MAGIC; 833 p->data = data; 834 835 *context = (perf_context_t) p; 836} 837 838/***************************************************************************/ 839 840idl_boolean perf_test_context 841( 842 perf_context_t context, 843 unsigned32 *data 844) 845{ 846 struct context *p = (struct context *) context; 847 848 if (p->magic != CONTEXT_MAGIC) 849 { 850 fprintf(stderr, "*** context mismatch; %08lx != %08x\n", p->magic, CONTEXT_MAGIC); 851 return (false); 852 } 853 854 *data = p->data; 855 856 return (true); 857} 858 859/***************************************************************************/ 860 861idl_boolean perf_free_context 862( 863 perf_context_t *context, 864 unsigned32 *data 865) 866{ 867 struct context *p = (struct context *) *context; 868 869 *context = NULL; 870 871 if (p->magic != CONTEXT_MAGIC) 872 { 873 fprintf(stderr, "*** context mismatch; %08lx != %08x\n", p->magic, CONTEXT_MAGIC); 874 return (false); 875 } 876 877 *data = p->data; 878 879 free(p); 880 881 return (true); 882} 883 884/***************************************************************************/ 885 886void perf_brd_fault 887( 888 handle_t h 889) 890{ 891 common(); 892 n_brd++; 893 print_binding_info ("perf_brd_fault", h); 894 RAISE (rpc_x_unknown_remote_fault); 895} 896 897 898/***************************************************************************/ 899 900perf_v2_0_epv_t perf_epv = 901{ 902 perf_init, 903 perf_info, 904 perf_null, 905 perf_null_idem, 906 perf_in, 907 perf_in_idem, 908 perf_out, 909 perf_out_idem, 910 perf_brd, 911 perf_maybe, 912 perf_brd_maybe, 913 perf_fp_test, 914 perf_register_b, 915 perf_unregister_b, 916 perf_exception, 917 perf_null_slow, 918 perf_null_slow_idem, 919 perf_shutdown, 920 perf_call_callback, 921 perf_get_context, 922 perf_test_context, 923 perf_free_context, 924 perf_shutdown2, 925 perf_brd_fault 926}; 927