1/* cilkview.h -*-C++-*- 2 * 3 ************************************************************************* 4 * 5 * @copyright 6 * Copyright (C) 2010-2013, Intel Corporation 7 * All rights reserved. 8 * 9 * @copyright 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * * Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * * Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * * Neither the name of Intel Corporation nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * @copyright 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 32 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 33 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 35 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 * 38 **************************************************************************/ 39 40#ifndef INCLUDED_CILKVIEW_H 41#define INCLUDED_CILKVIEW_H 42 43#include <cilk/cilk_api.h> 44 45#ifdef _WIN32 46# ifndef _WINBASE_ 47__CILKRTS_BEGIN_EXTERN_C 48unsigned long __stdcall GetTickCount(); 49__CILKRTS_END_EXTERN_C 50# endif 51#endif // _WIN32 52 53#if defined __unix__ || defined __APPLE__ || defined __VXWORKS__ 54# include <sys/time.h> 55#endif // defined __unix__ || defined __APPLE__ 56 57/// @brief Return the system clock with millisecond resolution 58/// 59/// This function returns a long integer representing the number of 60/// milliseconds since an arbitrary starting point, e.g., since the system was 61/// started or since the Unix Epoch. The result is meaningless by itself, but 62/// the difference between two sequential calls to __cilkview_getticks() 63/// represents the time interval that elapsed between them (in ms). 64static inline unsigned long long __cilkview_getticks() 65{ 66#if __INTEL_COMPILER > 1200 67 // When inlined, prevent code motion around this call 68 __notify_zc_intrinsic((void*) "test_getticks_start", 0); 69#endif 70 71#ifdef _WIN32 72 // Return milliseconds elapsed since the system started 73 return GetTickCount(); 74#elif defined(__unix__) || defined(__APPLE__) || defined __VXWORKS__ 75 // Return milliseconds elapsed since the Unix Epoch 76 // (1-Jan-1970 00:00:00.000 UTC) 77 struct timeval t; 78 gettimeofday(&t, 0); 79 return t.tv_sec * 1000ULL + t.tv_usec / 1000; 80#else 81# error test_getticks() not implemented for this OS 82#endif 83 84#if __INTEL_COMPILER > 1200 85 // When inlined, prevent code motion around this call 86 __notify_zc_intrinsic((void*) "test_getticks_end", 0); 87#endif 88} 89 90typedef struct 91{ 92 unsigned int size; // Size of structure in bytes 93 unsigned int status; // 1 = success, 0 = failure 94 unsigned long long time; // Time in milliseconds 95 unsigned long long work; 96 unsigned long long span; 97 unsigned long long burdened_span; 98 unsigned long long spawns; 99 unsigned long long syncs; 100 unsigned long long strands; 101 unsigned long long atomic_ins; 102 unsigned long long frames; 103} cilkview_data_t; 104 105typedef struct 106{ 107 cilkview_data_t *start; // Values at start of interval 108 cilkview_data_t *end; // Values at end of interval 109 const char *label; // Name for this interval 110 unsigned int flags; // What to do - see flags below 111} cilkview_report_t; 112 113// What __cilkview_report should do. The flags can be ORed together 114enum 115{ 116 CV_REPORT_WRITE_TO_LOG = 1, // Write parallelism report to the log (xml or text) 117 CV_REPORT_WRITE_TO_RESULTS = 2 // Write parallelism data to results file 118}; 119 120#ifndef CILKVIEW_NO_REPORT 121static void __cilkview_do_report(cilkview_data_t *start, 122 cilkview_data_t *end, 123 const char *label, 124 unsigned int flags); 125#endif /* CILKVIEW_NO_REPORT */ 126 127/* 128 * Metacall data 129 * 130 * A metacall is a way to pass data to a function implemented by a tool. 131 * Metacalls are always instrumented when the tool is loaded. 132 */ 133 134// Tool code for Cilkview 135#define METACALL_TOOL_CILKVIEW 2 136 137// Metacall codes implemented by Cilkview 138enum 139{ 140 CV_METACALL_PUTS, 141 CV_METACALL_QUERY, 142 CV_METACALL_START, 143 CV_METACALL_STOP, 144 CV_METACALL_RESET, 145 CV_METACALL_USE_DEFAULT_GRAIN, 146 CV_METACALL_CONNECTED, 147 CV_METACALL_SUSPEND, 148 CV_METACALL_RESUME, 149 CV_METACALL_REPORT 150}; 151 152#if ! defined(CILK_STUB) && defined(__INTEL_COMPILER) 153# define __cilkview_metacall(code,data) \ 154 __cilkrts_metacall(METACALL_TOOL_CILKVIEW, code, data) 155#else 156# define __cilkview_metacall(annotation,expr) (annotation, (void) (expr)) 157#endif 158 159// Write arbitrary string to the log 160#define __cilkview_puts(arg) \ 161 __cilkview_metacall(CV_METACALL_PUTS, arg) 162 163// Retrieve the Cilkview performance counters. The parameter must be a 164// cilkview_data_t 165#define __cilkview_query(d) \ 166 do { \ 167 d.size = sizeof(d); \ 168 d.status = 0; \ 169 __cilkview_metacall(CV_METACALL_QUERY, &d); \ 170 if (0 == d.status) \ 171 d.time = __cilkview_getticks(); \ 172 } while (0) 173 174// Write report to log or results file. If end is NULL, Cilkview will 175// use the current values. 176#define __cilkview_report(start, end, label, flags) \ 177 __cilkview_do_report(start, end, label, flags) 178 179// Control the workspan performance counters for the final report 180#define __cilkview_workspan_start() \ 181 __cilkview_metacall(CV_METACALL_START, 0) 182#define __cilkview_workspan_stop() \ 183 __cilkview_metacall(CV_METACALL_STOP, 0) 184#define __cilkview_workspan_reset() \ 185 __cilkview_metacall(CV_METACALL_RESET, 0) 186#define __cilkview_workspan_suspend() \ 187 __cilkview_metacall(CV_METACALL_SUSPEND, 0) 188#define __cilkview_workspan_resume() \ 189 __cilkview_metacall(CV_METACALL_RESUME, 0) 190 191#define __cilkview_use_default_grain_size() \ 192 __cilkview_metacall(CV_METACALL_USE_DEFAULT, 0) 193 194// Sets the int is_connected to 1 if Cilkview is active 195#define __cilkview_connected(is_connected) \ 196 __cilkview_metacall(CV_METACALL_CONNECTED, &is_connected) 197 198 199#ifndef CILKVIEW_NO_REPORT 200 201// Stop Microsoft include files from complaining about getenv and fopen 202#define _CRT_SECURE_NO_WARNINGS 203 204#include <stdlib.h> 205#include <stdio.h> 206 207#ifdef _WIN32 208#pragma warning(push) 209#pragma warning(disable: 1786) // Suppress warnings that getenv, fopen are deprecated 210#endif 211 212static void __cilkview_do_report(cilkview_data_t *start, 213 cilkview_data_t *end, 214 const char *label, 215 unsigned int flags) 216{ 217 int under_cilkview = 0; 218 unsigned long long elapsed_ms; 219 int worker_count = 0; 220 char *nworkers; 221 char *outfile; 222 FILE *f; 223 224 // Check whether we're running under Cilkview 225 __cilkview_connected(under_cilkview); 226 227 // If we're running under Cilkview, let it do those things that need 228 // to be done 229 if (under_cilkview) 230 { 231 cilkview_report_t d = {start, end, label, flags}; 232 __cilkview_metacall(CV_METACALL_REPORT, &d); 233 return; 234 } 235 236 // We're not running under Cilkview. 237 // 238 // If we weren't asked to write to the results file, we're done. 239 if (0 == (flags & CV_REPORT_WRITE_TO_RESULTS)) 240 return; 241 242 // Calculate the elapse milliseconds 243 if (NULL == end) 244 elapsed_ms = __cilkview_getticks() - start->time; 245 else 246 elapsed_ms = end->time - start->time; 247 248 // Determine how many workers we're using for this trial run 249 nworkers = getenv("CILK_NWORKERS"); 250 if (NULL != nworkers) 251 worker_count = atoi(nworkers); 252 if (0 == worker_count) 253 worker_count = 16; 254 255 // Open the output file and write the trial data to it 256 outfile = getenv("CILKVIEW_OUTFILE"); 257 if (NULL == outfile) 258 outfile = (char *)"cilkview.out"; 259 260 f = fopen(outfile, "a"); 261 if (NULL == f) 262 fprintf(stderr, "__cilkview_do_report: unable to append to file %s\n", outfile); 263 else 264 { 265 fprintf(f, "%s trial %d %f\n", label, 266 worker_count, 267 ((float)elapsed_ms) / 1000.0f); 268 fclose(f); 269 } 270} 271#ifdef _WIN32 272#pragma warning(pop) 273#endif 274 275#endif // CILKVIEW_NO_REPORT 276 277 278#endif /* ! defined(INCLUDED_CILKVIEW_H) */ 279