Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
MoreMultiprocessing/MoreMPLog.h
/* |
File: MoreMPLog.h |
Contains: MP-safe logging. |
Written by: Quinn |
Copyright: Copyright © 2000 by Apple Computer, Inc., All Rights Reserved. |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
("Apple") in consideration of your agreement to the following terms, and your |
use, installation, modification or redistribution of this Apple software |
constitutes acceptance of these terms. If you do not agree with these terms, |
please do not use, install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and subject |
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs |
copyrights in this original Apple software (the "Apple Software"), to use, |
reproduce, modify and redistribute the Apple Software, with or without |
modifications, in source and/or binary forms; provided that if you redistribute |
the Apple Software in its entirety and without modifications, you must retain |
this notice and the following text and disclaimers in all such redistributions of |
the Apple Software. Neither the name, trademarks, service marks or logos of |
Apple Computer, Inc. may be used to endorse or promote products derived from the |
Apple Software without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or implied, |
are granted by Apple herein, including but not limited to any patent rights that |
may be infringed by your derivative works or by other works in which the Apple |
Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Change History (most recent first): |
<4> 21/9/01 Quinn Changes for CWPro7 Mach-O build. |
<3> 9/7/01 Quinn Removed MPLogPrintfSlow because of problems I'm having on Mac OS |
9.1. |
<2> 5/7/01 Quinn Delete space between MPLog and ( in macro definition. It |
previously didn't do what I wanted it to do, although it was |
somewhat prettier. |
<1> 7/11/00 Quinn First checked in. |
*/ |
#pragma once |
///////////////////////////////////////////////////////////////// |
// MoreIsBetter Setup |
#include "MoreSetup.h" |
// Mac OS interfaces |
#if ! MORE_FRAMEWORK_INCLUDES |
#include <Files.h> |
#endif |
///////////////////////////////////////////////////////////////// |
#ifdef __cplusplus |
extern "C" { |
#endif |
///////////////////////////////////////////////////////////////////// |
// Overview |
// -------- |
// This module implements a very low-level logging mechanism that is safe |
// to call from /all/ contexts, including MP tasks and interrupts. It was |
// originally written to help develop OTMP (another part of MoreIsBetter) but |
// it is generally useful. |
// |
// The core design is stolen directly from "InterruptSafeDebug", another |
// MoreIsBetterModule. The main change is that this module logs into |
// memory rather than directly to the screen. I should unify these two |
// modules eventually, but at the moment I'm concentrating on shipping |
// OTMP. |
// |
// The log data goes into a log buffer pointed to by gMPLogBuffer. |
// After a crash you can find this buffer in MacsBug and then look |
// through the buffer for a '¥' character to find the last item logged. |
// When you start up the module it defines a MacsBug macro, MPLog, to do |
// this for you. |
// |
// For InterfaceLib-based code you can call this library when paging is |
// unsafe, as long as your guarantee that the library's code and global |
// data is held. This is typically the case for device driver code. |
// For Carbon code, paging must be safe when you call this module. |
// Paging is always safe on Mac OS X, and is typically safe in application- |
// level code on traditional Mac OS. See Technote 1094 "Virtual Memory |
// Application Compatibility" for a list of situations when paging is |
// unsafe on traditional Mac OS. |
///////////////////////////////////////////////////////////////////// |
// Core Logging Routines |
extern pascal OSStatus InitMPLog(ByteCount logBufferSize); |
// Initialises the MP-safe log to contain a log of logBufferSize |
// bytes. The buffer is allocated in the current zone using NewPtrClear. |
// logBufferSize must be a power of 2. |
extern pascal void TermMPLog(void); |
// Shuts down the MP-safe log. Do not call this routine while |
// there are MP threads running that are logging data. |
extern pascal void MPLogText(const UInt8 *text, ByteCount len); |
// Log's the text described by text and len to the buffer. |
extern pascal OSStatus MPLogWriteToFile(const FSSpec *fss); |
// Writes the MP log to the file pointed to by fss, |
// overwriting any data that was there previously. This |
// routine is not coordinated with the logging, so if |
// there is ongoing logging happening while the write is |
// in progress you will get weird results. |
///////////////////////////////////////////////////////////////////// |
// Log Points |
// The followed routines let you easily define log points throughout |
// your code. They are conditionalised with the MORE_DEBUG macro so |
// the log points go away when you compile a non-debug version. They |
// are runtime conditionalised by a mask, so you can selectively enable |
// logging from a particular part of your code at runtime. The "module" |
// parameter to each MPLog routine is a bit number in this mask. If the |
// bit is set, the log entry is created. |
// |
// IMPORTANT: The default value for the log mask is 0, so you'll have to |
// set it yourself if you expect to see anything in the log. |
// |
// Log points are identified by a tag, ie an OSType that you can easily |
// recognise. I use an OSType rather than a string because it's fast |
// and simple. This module encourages you to use tags of the form '>Foo' |
// for routine entry points and '<Foo' for routine exit points. MPLogTagReturn |
// takes an entry point tag and returns the equivalent return tag. |
// |
// Log points can take up to four parameters. These parameters are |
// written to the log as hex. |
#define MPLogTagReturn(tag) ( ((tag) & 0x00FFFFFF) | ('<' << 24) ) |
#if MORE_DEBUG |
extern pascal void MPLogSetMask(UInt32 logMask); |
// Sets the log mask. Only log points whose bit is set in this |
// mask will actually appear in the log. |
extern pascal UInt32 MPLogGetMask(void); |
// Returns the mask last set with MPLogSetMask. |
extern pascal void MPLog(UInt32 module, OSType tag); |
extern pascal void MPLog1(UInt32 module, OSType tag, const void *p1); |
extern pascal void MPLog2(UInt32 module, OSType tag, const void *p1, const void *p2); |
extern pascal void MPLog3(UInt32 module, OSType tag, const void *p1, const void *p2, const void *p3); |
extern pascal void MPLog4(UInt32 module, OSType tag, const void *p1, const void *p2, const void *p3, const void *p4); |
// If the bit whose number is "module" is set in the log mask, |
// create a log entry recording "tag" and "pX". |
// Safe to call from all execution environments. |
// You must initialise the log buffer, using InitMPLog, |
// before calling this routine. |
#else |
// Macros so that non-debug code will compile. |
#define MPLogSetMask(logMask) |
#define MPLogGetMask() 0 |
#define MPLog(module, tag) |
#define MPLog1(module, tag, p1) |
#define MPLog2(module, tag, p1, p2) |
#define MPLog3(module, tag, p1, p2, p3) |
#define MPLog4(module, tag, p1, p2, p3, p4) |
#endif |
///////////////////////////////////////////////////////////////////// |
// Utility printf Routines |
extern void MPLogPrintf(const char *format, ...); |
// Like printf, but result goes to the MP log. |
// Safe to call from all execution environments. |
// You must initialise the log buffer, using InitMPLog, |
// before calling this routine. |
// |
// The fully expanded string must be 256 characters or less. |
#if 0 |
// This routine is fatally broken and I'm not entirely sure |
// why. Something about the MPRemoteCall is causing the MP |
// task to wedge. I believe this is a bug in Mac OS 9.1 |
// [2607064] because it works just fine on Mac OS 9.0.4 and |
// pre-release versions of Mac OS 9.2. Until I figure this |
// out I'm just not going use this routine. |
extern void MPLogPrintfSlow(const char *format, ...); |
// MP-safe version of printf. Result goes to console. |
// The routine is slow because it does an MPRemoteCall to |
// do the printing, which means the MP task waits until |
// the application is scheduled and can run the called |
// routine before it unblocks. |
// |
// You cannot call this routine from an interrupt. You can only |
// call it from system task code or from an MP task. |
// |
// You don't need to call InitMPLog before calling this routine. |
// |
// Doesn't strictly belong in this module, but it was a convenient |
// place to put it. |
#endif |
#ifdef __cplusplus |
} |
#endif |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22