/* * Mach Operating System * Copyright (c) 1991,1990,1989 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ /* * Copyright 1991 by Open Software Foundation, * Grenoble, FRANCE * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appears in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation, and that the name of OSF or Open Software * Foundation not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior * permission. * * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _MACH_PROFIL_H_ #define _MACH_PROFIL_H_ #include #include #include #define NB_PROF_BUFFER 2 /* number of buffers servicing a * profiled thread */ #define SIZE_PROF_BUFFER 100 /* size of a profil buffer (in int) * This values is also defined in * the server (ugly), be careful ! */ struct prof_data { ipc_object_t prof_port; /* where to send a full buffer */ struct buffer { int *p_zone; /* points to the actual storage area */ int p_index;/* next slot to be filled */ boolean_t p_full; /* is the current buffer full ? */ } prof_area[NB_PROF_BUFFER]; int prof_index; /* index of the buffer structure * currently in use */ }; typedef struct prof_data *prof_data_t; #define NULLPBUF ((prof_data_t) 0) typedef struct buffer *buffer_t; /* Macros */ #define set_pbuf_nb(pbuf, nb) \ (((nb) >= 0 && (nb) < NB_PROF_BUFFER) \ ? (pbuf)->prof_index = (nb), 1 \ : 0) #define get_pbuf_nb(pbuf) \ (pbuf)->prof_index extern vm_map_t kernel_map; #define dealloc_pbuf_area(pbuf) \ { \ register int i; \ \ for(i=0; i < NB_PROF_BUFFER ; i++) \ kmem_free(kernel_map, \ (vm_offset_t) (pbuf)->prof_area[i].p_zone, \ SIZE_PROF_BUFFER*sizeof(int)); \ kmem_free(kernel_map, \ (vm_offset_t)(pbuf), \ sizeof(struct prof_data)); \ } #define alloc_pbuf_area(pbuf, vmpbuf) \ (vmpbuf) = (vm_offset_t) 0; \ if (kmem_alloc(kernel_map, &(vmpbuf) , sizeof(struct prof_data)) == \ KERN_SUCCESS) { \ register int i; \ register boolean_t end; \ \ (pbuf) = (prof_data_t) (vmpbuf); \ for(i=0, end=FALSE; i < NB_PROF_BUFFER && end == FALSE; i++) { \ (vmpbuf) = (vm_offset_t) 0; \ if (kmem_alloc(kernel_map,&(vmpbuf),SIZE_PROF_BUFFER*sizeof(int)) == KERN_SUCCESS) { \ (pbuf)->prof_area[i].p_zone = (int *) (vmpbuf); \ (pbuf)->prof_area[i].p_full = FALSE; \ } \ else { \ (pbuf) = NULLPBUF; \ end = TRUE; \ } \ } \ } \ else \ (pbuf) = NULLPBUF; /* MACRO set_pbuf_value ** ** enters the value 'val' in the buffer 'pbuf' and returns the following ** indications: 0: means that a fatal error occurred: the buffer was full ** (it hasn't been sent yet) ** 1: means that a value has been inserted successfully ** 2: means that we'v just entered the last value causing ** the current buffer to be full.(must switch to ** another buffer and signal the sender to send it) */ #define set_pbuf_value(pbuf, val) \ { \ register buffer_t a = &((pbuf)->prof_area[(pbuf)->prof_index]); \ register int i = a->p_index++; \ register boolean_t f = a->p_full; \ \ if (f == TRUE ) \ *(val) = 0; \ else { \ a->p_zone[i] = *(val); \ if (i == SIZE_PROF_BUFFER-1) { \ a->p_full = TRUE; \ *(val) = 2; \ } \ else \ *(val) = 1; \ } \ } #define reset_pbuf_area(pbuf) \ { \ register int *i = &((pbuf)->prof_index); \ \ *i = (*i == NB_PROF_BUFFER-1) ? 0 : ++(*i); \ (pbuf)->prof_area[*i].p_index = 0; \ } /**************************************************************/ /* Structure, elements used for queuing operations on buffers */ /**************************************************************/ #define thread_t int * /* ** This must be done in order to avoid a circular inclusion ** with file kern/thread.h . ** When using this data structure, one must cast the actual ** type, this is (int *) or (thread_t) */ struct buf_to_send { queue_chain_t list; thread_t thread; int number; /* the number of the buffer to be sent */ char wakeme; /* do wakeup when buffer has been sent */ } ; #undef thread_t typedef struct buf_to_send *buf_to_send_t; #define NULLBTS ((buf_to_send_t) 0) /* ** Global variable: the head of the queue of buffers to send ** It is a queue with locks (uses macros from queue.h) and it ** is shared by hardclock() and the sender_thread() */ mpqueue_head_t prof_queue; #endif /* _MACH_PROF_H_ */