Swarm-NG  1.1
gpulog_logrecord.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2010 by Mario Juric *
3  * mjuric@cfa.harvard.EDU *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 3 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
27 #ifndef bits_gpulog_logrecord_h__
28 #define bits_gpulog_logrecord_h__
29 
30 namespace gpulog
31 {
32 namespace internal
33 {
34 
35  /*
36  Log unserialization infrastructure
37  */
38 
40  struct logrecord
41  {
42  const char *ptr;
43  int at;
44 
45  #if ARGINFO
46  int atarg;
47  __host__ __device__ inline const arginfo &get_arginfo(int arg) const { return *((arginfo *)(ptr + hdr().infos) + arg); }
48  #endif
49 
51  __host__ __device__ inline logrecord() : ptr(NULL), at(0) { IFARGINFO(atarg = 1); }
53  __host__ __device__ inline logrecord(const char *ptr_) : ptr(ptr_), at(hdr().dataoffset()) { IFARGINFO(atarg = 1); }
54 
56  __host__ __device__ inline const header &hdr() const { return *(header *)ptr; }
58  __host__ __device__ inline operator bool() const { return at < hdr().len; }
59 
61  __host__ __device__ inline int len() const { return hdr().len; }
63  __host__ __device__ inline int msgid() const { return hdr().msgid; }
64  };
65 
66  /* workaround for CUDA 2.2 template parsing bug */
67  typedef logrecord& logrecord_ref;
68 
69  template<typename T>
70  __device__ void assert_arg_compatible(logrecord &in, T &v)
71  {
72  #if ARGINFO && !__CUDACC__
73  const arginfo &ai = in.get_arginfo(in.atarg);
74  typedef ttrait<T> TT;
75 
76  DHOST( std::cerr << " Log : " << ai << "\n"; )
77  DHOST( std::cerr << " Host : arg=" << in.atarg << " align=" << TT::align << " size=" << TT::size << " dim=" << TT::dim << " isptr=" << TT::isptr << "\n"; )
78 
79  #define AITEST(a, TT, b) \
80  if(a != TT::b) \
81  { \
82  std::cerr << "Assertion failed GPUTypeTraits::" #a " != HostTypeTraits::" #b << " (" << a << " != " << TT::b << ")\n"; \
83  std::cerr << " Log : " << ai << "\n"; \
84  std::cerr << " Host : arg=" << in.atarg << " align=" << TT::align << " size=" << TT::size << " dim=" << TT::dim << " isptr=" << TT::isptr << "\n"; \
85  assert(a == TT::b); \
86  }
87 
88  // Check for most common issues
89  // TODO: We could make this more sophisticated to check for correct extraction
90  // of presized arrays, as well as the last array<>.
91  AITEST( ai.align, TT, align ); // check for alignment
92  AITEST( ai.size, TT, size ); // check for scalar type size match
93  #undef AITEST
94 
95  if(in.atarg+1 < in.hdr().nargs) { in.atarg++; }
96  #endif
97  }
98 
100  template<typename T>
101  __device__ inline logrecord_ref operator >>(logrecord &in, T &v)
102  {
103  if(!in) { return in; }
104 
105  // compute alignment
106  int offs = ASTART(in.at, ALIGNOF(T));
107  in.at = offs + sizeof(T);
108  assert_arg_compatible(in, v);
109  dev_assert(in.at <= in.len()); /* assert we didn't run over the size of the buffer */
110 
111  v = *(T*)(in.ptr + offs);
112 
113  DHOST( std::cerr << "reading scalar POD: offs = " << offs << " val = " << v << "\n"; )
114 
115  return in;
116  }
117 
119  template<typename T, int N>
120  __device__ inline logrecord_ref operator >>(logrecord &in, const T (&v)[N])
121  {
122  if(!in) { return in; }
123 
124  // compute alignment
125  int offs = ASTART(in.at, ALIGNOF(T));
126  in.at = offs + sizeof(T)*N;
127  assert_arg_compatible(in, v);
128  dev_assert(in.at <= in.len()); /* assert we didn't run over the size of the buffer */
129 
130  for(int i = 0; i != N; i++)
131  {
132  v[i] = ((T*)(in.ptr + offs))[i];
133  DHOST( std::cerr << "reading array: offs = " << offs << " N = " << N << " val[" << i << "] = " << v[i] << "\n"; )
134  }
135 
136  return in;
137  }
138 
140  __device__ inline logrecord_ref operator>>(logrecord &in, char *v)
141  {
142  if(!in) { return in; }
143 
144  // compute alignment
145  DHOST( char *v0 = v; int offs = in.at; )
146  assert_arg_compatible(in, v);
147  while(in.ptr[in.at])
148  {
149  *v = in.ptr[in.at++];
150  v++;
151  }
152  *v = 0; in.at++;
153 
154  dev_assert(in.at <= in.len()); /* assert we didn't run over the size of the buffer */
155 
156  DHOST( std::cerr << "reading character string: offs = " << offs << " val = " << v0 << " endoff = " << in.at << "\n"; )
157  return in;
158  }
159 
161  template<int N>
162  __device__ inline logrecord_ref operator>>(logrecord &in, char v[N])
163  {
164  return in >> (char *)v;
165  }
166 
168  template<typename T>
169  __device__ inline logrecord_ref operator >>(logrecord &in, T *&v)
170  {
171  // intentionally force a compile time error - you MUST only be using
172  // the const T* version (below), as the internal buffer to which a
173  // pointer is returned is immutable
174  STATIC_ASSERTION_FAILED__Your_pointer_must_be_to_const_T_and_not_just_T______(v);
175  return in;
176  }
177 
179  template<typename T>
180  __device__ inline logrecord_ref operator >>(logrecord &in, const T *&v)
181  {
182  if(!in) { return in; }
183 
184  // compute alignment
185  int offs = ASTART(in.at, ALIGNOF(T));
186  assert_arg_compatible(in, v);
187  v = (const T*)(in.ptr + offs);
188  in.at = in.hdr().len; // extraction of an array of unspecified size is always the last operation
189 
190  DHOST( std::cerr << "reading unbound array : offs = " << offs << " v = " << (void*)v << " v[0] = " << *v << "\n"; )
191  DHOST( std::cerr << (char*)v - in.ptr << "\n"; )
192 
193  return in;
194  }
195 
196 }
197 }
198 
199 #endif // bits_gpulog_logrecord_h__