oacc-mem.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541
  1. /* OpenACC Runtime initialization routines
  2. Copyright (C) 2013-2022 Free Software Foundation, Inc.
  3. Contributed by Mentor Embedded.
  4. This file is part of the GNU Offloading and Multi Processing Library
  5. (libgomp).
  6. Libgomp is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3, or (at your option)
  9. any later version.
  10. Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. more details.
  14. Under Section 7 of GPL version 3, you are granted additional
  15. permissions described in the GCC Runtime Library Exception, version
  16. 3.1, as published by the Free Software Foundation.
  17. You should have received a copy of the GNU General Public License and
  18. a copy of the GCC Runtime Library Exception along with this program;
  19. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  20. <http://www.gnu.org/licenses/>. */
  21. #include "openacc.h"
  22. #include "libgomp.h"
  23. #include "gomp-constants.h"
  24. #include "oacc-int.h"
  25. #include <string.h>
  26. #include <assert.h>
  27. /* Return block containing [H->S), or NULL if not contained. The device lock
  28. for DEV must be locked on entry, and remains locked on exit. */
  29. static splay_tree_key
  30. lookup_host (struct gomp_device_descr *dev, void *h, size_t s)
  31. {
  32. struct splay_tree_key_s node;
  33. splay_tree_key key;
  34. node.host_start = (uintptr_t) h;
  35. node.host_end = (uintptr_t) h + s;
  36. key = splay_tree_lookup (&dev->mem_map, &node);
  37. return key;
  38. }
  39. /* Helper for lookup_dev. Iterate over splay tree. */
  40. static splay_tree_key
  41. lookup_dev_1 (splay_tree_node node, uintptr_t d, size_t s)
  42. {
  43. splay_tree_key key = &node->key;
  44. if (d >= key->tgt->tgt_start && d + s <= key->tgt->tgt_end)
  45. return key;
  46. key = NULL;
  47. if (node->left)
  48. key = lookup_dev_1 (node->left, d, s);
  49. if (!key && node->right)
  50. key = lookup_dev_1 (node->right, d, s);
  51. return key;
  52. }
  53. /* Return block containing [D->S), or NULL if not contained.
  54. This iterates over the splay tree. This is not expected to be a common
  55. operation.
  56. The device lock associated with MEM_MAP must be locked on entry, and remains
  57. locked on exit. */
  58. static splay_tree_key
  59. lookup_dev (splay_tree mem_map, void *d, size_t s)
  60. {
  61. if (!mem_map || !mem_map->root)
  62. return NULL;
  63. return lookup_dev_1 (mem_map->root, (uintptr_t) d, s);
  64. }
  65. /* OpenACC is silent on how memory exhaustion is indicated. We return
  66. NULL. */
  67. void *
  68. acc_malloc (size_t s)
  69. {
  70. if (!s)
  71. return NULL;
  72. goacc_lazy_initialize ();
  73. struct goacc_thread *thr = goacc_thread ();
  74. assert (thr->dev);
  75. if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  76. return malloc (s);
  77. acc_prof_info prof_info;
  78. acc_api_info api_info;
  79. bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
  80. void *res = thr->dev->alloc_func (thr->dev->target_id, s);
  81. if (profiling_p)
  82. {
  83. thr->prof_info = NULL;
  84. thr->api_info = NULL;
  85. }
  86. return res;
  87. }
  88. void
  89. acc_free (void *d)
  90. {
  91. splay_tree_key k;
  92. if (!d)
  93. return;
  94. struct goacc_thread *thr = goacc_thread ();
  95. assert (thr && thr->dev);
  96. struct gomp_device_descr *acc_dev = thr->dev;
  97. if (acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  98. return free (d);
  99. acc_prof_info prof_info;
  100. acc_api_info api_info;
  101. bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
  102. gomp_mutex_lock (&acc_dev->lock);
  103. /* We don't have to call lazy open here, as the ptr value must have
  104. been returned by acc_malloc. It's not permitted to pass NULL in
  105. (unless you got that null from acc_malloc). */
  106. if ((k = lookup_dev (&acc_dev->mem_map, d, 1)))
  107. {
  108. void *offset = d - k->tgt->tgt_start + k->tgt_offset;
  109. void *h = k->host_start + offset;
  110. size_t h_size = k->host_end - k->host_start;
  111. gomp_mutex_unlock (&acc_dev->lock);
  112. /* PR92503 "[OpenACC] Behavior of 'acc_free' if the memory space is still
  113. used in a mapping". */
  114. gomp_fatal ("refusing to free device memory space at %p that is still"
  115. " mapped at [%p,+%d]",
  116. d, h, (int) h_size);
  117. }
  118. else
  119. gomp_mutex_unlock (&acc_dev->lock);
  120. if (!acc_dev->free_func (acc_dev->target_id, d))
  121. gomp_fatal ("error in freeing device memory in %s", __FUNCTION__);
  122. if (profiling_p)
  123. {
  124. thr->prof_info = NULL;
  125. thr->api_info = NULL;
  126. }
  127. }
  128. static void
  129. memcpy_tofrom_device (bool from, void *d, void *h, size_t s, int async,
  130. const char *libfnname)
  131. {
  132. /* No need to call lazy open here, as the device pointer must have
  133. been obtained from a routine that did that. */
  134. struct goacc_thread *thr = goacc_thread ();
  135. assert (thr && thr->dev);
  136. if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  137. {
  138. if (from)
  139. memmove (h, d, s);
  140. else
  141. memmove (d, h, s);
  142. return;
  143. }
  144. acc_prof_info prof_info;
  145. acc_api_info api_info;
  146. bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
  147. if (profiling_p)
  148. {
  149. prof_info.async = async;
  150. prof_info.async_queue = prof_info.async;
  151. }
  152. goacc_aq aq = get_goacc_asyncqueue (async);
  153. if (from)
  154. gomp_copy_dev2host (thr->dev, aq, h, d, s);
  155. else
  156. gomp_copy_host2dev (thr->dev, aq, d, h, s, false, /* TODO: cbuf? */ NULL);
  157. if (profiling_p)
  158. {
  159. thr->prof_info = NULL;
  160. thr->api_info = NULL;
  161. }
  162. }
  163. void
  164. acc_memcpy_to_device (void *d, void *h, size_t s)
  165. {
  166. memcpy_tofrom_device (false, d, h, s, acc_async_sync, __FUNCTION__);
  167. }
  168. void
  169. acc_memcpy_to_device_async (void *d, void *h, size_t s, int async)
  170. {
  171. memcpy_tofrom_device (false, d, h, s, async, __FUNCTION__);
  172. }
  173. void
  174. acc_memcpy_from_device (void *h, void *d, size_t s)
  175. {
  176. memcpy_tofrom_device (true, d, h, s, acc_async_sync, __FUNCTION__);
  177. }
  178. void
  179. acc_memcpy_from_device_async (void *h, void *d, size_t s, int async)
  180. {
  181. memcpy_tofrom_device (true, d, h, s, async, __FUNCTION__);
  182. }
  183. /* Return the device pointer that corresponds to host data H. Or NULL
  184. if no mapping. */
  185. void *
  186. acc_deviceptr (void *h)
  187. {
  188. splay_tree_key n;
  189. void *d;
  190. void *offset;
  191. goacc_lazy_initialize ();
  192. struct goacc_thread *thr = goacc_thread ();
  193. struct gomp_device_descr *dev = thr->dev;
  194. if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  195. return h;
  196. /* In the following, no OpenACC Profiling Interface events can possibly be
  197. generated. */
  198. gomp_mutex_lock (&dev->lock);
  199. n = lookup_host (dev, h, 1);
  200. if (!n)
  201. {
  202. gomp_mutex_unlock (&dev->lock);
  203. return NULL;
  204. }
  205. offset = h - n->host_start;
  206. d = n->tgt->tgt_start + n->tgt_offset + offset;
  207. gomp_mutex_unlock (&dev->lock);
  208. return d;
  209. }
  210. /* Return the host pointer that corresponds to device data D. Or NULL
  211. if no mapping. */
  212. void *
  213. acc_hostptr (void *d)
  214. {
  215. splay_tree_key n;
  216. void *h;
  217. void *offset;
  218. goacc_lazy_initialize ();
  219. struct goacc_thread *thr = goacc_thread ();
  220. struct gomp_device_descr *acc_dev = thr->dev;
  221. if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  222. return d;
  223. /* In the following, no OpenACC Profiling Interface events can possibly be
  224. generated. */
  225. gomp_mutex_lock (&acc_dev->lock);
  226. n = lookup_dev (&acc_dev->mem_map, d, 1);
  227. if (!n)
  228. {
  229. gomp_mutex_unlock (&acc_dev->lock);
  230. return NULL;
  231. }
  232. offset = d - n->tgt->tgt_start + n->tgt_offset;
  233. h = n->host_start + offset;
  234. gomp_mutex_unlock (&acc_dev->lock);
  235. return h;
  236. }
  237. /* Return 1 if host data [H,+S] is present on the device. */
  238. int
  239. acc_is_present (void *h, size_t s)
  240. {
  241. splay_tree_key n;
  242. if (!s || !h)
  243. return 0;
  244. goacc_lazy_initialize ();
  245. struct goacc_thread *thr = goacc_thread ();
  246. struct gomp_device_descr *acc_dev = thr->dev;
  247. if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  248. return h != NULL;
  249. /* In the following, no OpenACC Profiling Interface events can possibly be
  250. generated. */
  251. gomp_mutex_lock (&acc_dev->lock);
  252. n = lookup_host (acc_dev, h, s);
  253. if (n && ((uintptr_t)h < n->host_start
  254. || (uintptr_t)h + s > n->host_end
  255. || s > n->host_end - n->host_start))
  256. n = NULL;
  257. gomp_mutex_unlock (&acc_dev->lock);
  258. return n != NULL;
  259. }
  260. /* Create a mapping for host [H,+S] -> device [D,+S] */
  261. void
  262. acc_map_data (void *h, void *d, size_t s)
  263. {
  264. size_t mapnum = 1;
  265. void *hostaddrs = h;
  266. void *devaddrs = d;
  267. size_t sizes = s;
  268. unsigned short kinds = GOMP_MAP_ALLOC;
  269. goacc_lazy_initialize ();
  270. struct goacc_thread *thr = goacc_thread ();
  271. struct gomp_device_descr *acc_dev = thr->dev;
  272. if (acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  273. {
  274. if (d != h)
  275. gomp_fatal ("cannot map data on shared-memory system");
  276. }
  277. else
  278. {
  279. struct goacc_thread *thr = goacc_thread ();
  280. if (!d || !h || !s)
  281. gomp_fatal ("[%p,+%d]->[%p,+%d] is a bad map",
  282. (void *)h, (int)s, (void *)d, (int)s);
  283. acc_prof_info prof_info;
  284. acc_api_info api_info;
  285. bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
  286. gomp_mutex_lock (&acc_dev->lock);
  287. if (lookup_host (acc_dev, h, s))
  288. {
  289. gomp_mutex_unlock (&acc_dev->lock);
  290. gomp_fatal ("host address [%p, +%d] is already mapped", (void *)h,
  291. (int)s);
  292. }
  293. if (lookup_dev (&thr->dev->mem_map, d, s))
  294. {
  295. gomp_mutex_unlock (&acc_dev->lock);
  296. gomp_fatal ("device address [%p, +%d] is already mapped", (void *)d,
  297. (int)s);
  298. }
  299. gomp_mutex_unlock (&acc_dev->lock);
  300. struct target_mem_desc *tgt
  301. = goacc_map_vars (acc_dev, NULL, mapnum, &hostaddrs, &devaddrs, &sizes,
  302. &kinds, true, GOMP_MAP_VARS_ENTER_DATA);
  303. assert (tgt);
  304. assert (tgt->list_count == 1);
  305. splay_tree_key n = tgt->list[0].key;
  306. assert (n);
  307. assert (n->refcount == 1);
  308. assert (n->dynamic_refcount == 0);
  309. /* Special reference counting behavior. */
  310. n->refcount = REFCOUNT_INFINITY;
  311. if (profiling_p)
  312. {
  313. thr->prof_info = NULL;
  314. thr->api_info = NULL;
  315. }
  316. }
  317. }
  318. void
  319. acc_unmap_data (void *h)
  320. {
  321. struct goacc_thread *thr = goacc_thread ();
  322. struct gomp_device_descr *acc_dev = thr->dev;
  323. /* No need to call lazy open, as the address must have been mapped. */
  324. /* This is a no-op on shared-memory targets. */
  325. if (acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  326. return;
  327. acc_prof_info prof_info;
  328. acc_api_info api_info;
  329. bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
  330. gomp_mutex_lock (&acc_dev->lock);
  331. splay_tree_key n = lookup_host (acc_dev, h, 1);
  332. if (!n)
  333. {
  334. gomp_mutex_unlock (&acc_dev->lock);
  335. gomp_fatal ("%p is not a mapped block", (void *)h);
  336. }
  337. size_t host_size = n->host_end - n->host_start;
  338. if (n->host_start != (uintptr_t) h)
  339. {
  340. gomp_mutex_unlock (&acc_dev->lock);
  341. gomp_fatal ("[%p,%d] surrounds %p",
  342. (void *) n->host_start, (int) host_size, (void *) h);
  343. }
  344. /* TODO This currently doesn't catch 'REFCOUNT_INFINITY' usage different from
  345. 'acc_map_data'. Maybe 'dynamic_refcount' can be used for disambiguating
  346. the different 'REFCOUNT_INFINITY' cases, or simply separate
  347. 'REFCOUNT_INFINITY' values per different usage ('REFCOUNT_ACC_MAP_DATA'
  348. etc.)? */
  349. else if (n->refcount != REFCOUNT_INFINITY)
  350. {
  351. gomp_mutex_unlock (&acc_dev->lock);
  352. gomp_fatal ("refusing to unmap block [%p,+%d] that has not been mapped"
  353. " by 'acc_map_data'",
  354. (void *) h, (int) host_size);
  355. }
  356. struct target_mem_desc *tgt = n->tgt;
  357. if (tgt->refcount == REFCOUNT_INFINITY)
  358. {
  359. gomp_mutex_unlock (&acc_dev->lock);
  360. gomp_fatal ("cannot unmap target block");
  361. }
  362. /* Above, we've verified that the mapping must have been set up by
  363. 'acc_map_data'. */
  364. assert (tgt->refcount == 1);
  365. /* Nullifying these fields prevents 'gomp_unmap_tgt' via 'gomp_remove_var'
  366. from freeing the target memory. */
  367. tgt->tgt_end = 0;
  368. tgt->to_free = NULL;
  369. bool is_tgt_unmapped = gomp_remove_var (acc_dev, n);
  370. assert (is_tgt_unmapped);
  371. gomp_mutex_unlock (&acc_dev->lock);
  372. if (profiling_p)
  373. {
  374. thr->prof_info = NULL;
  375. thr->api_info = NULL;
  376. }
  377. }
  378. /* Helper function to map a single dynamic data item, represented by a single
  379. mapping. The acc_dev->lock should be held on entry, and remains locked on
  380. exit. */
  381. static void *
  382. goacc_map_var_existing (struct gomp_device_descr *acc_dev, void *hostaddr,
  383. size_t size, splay_tree_key n)
  384. {
  385. assert (n);
  386. /* Present. */
  387. void *d = (void *) (n->tgt->tgt_start + n->tgt_offset + hostaddr
  388. - n->host_start);
  389. if (hostaddr + size > (void *) n->host_end)
  390. {
  391. gomp_mutex_unlock (&acc_dev->lock);
  392. gomp_fatal ("[%p,+%d] not mapped", hostaddr, (int) size);
  393. }
  394. assert (n->refcount != REFCOUNT_LINK);
  395. if (n->refcount != REFCOUNT_INFINITY)
  396. n->refcount++;
  397. n->dynamic_refcount++;
  398. return d;
  399. }
  400. /* Enter dynamic mapping for a single datum. Return the device pointer. */
  401. static void *
  402. goacc_enter_datum (void **hostaddrs, size_t *sizes, void *kinds, int async)
  403. {
  404. void *d;
  405. splay_tree_key n;
  406. if (!hostaddrs[0] || !sizes[0])
  407. gomp_fatal ("[%p,+%d] is a bad range", hostaddrs[0], (int) sizes[0]);
  408. goacc_lazy_initialize ();
  409. struct goacc_thread *thr = goacc_thread ();
  410. struct gomp_device_descr *acc_dev = thr->dev;
  411. if (acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  412. return hostaddrs[0];
  413. acc_prof_info prof_info;
  414. acc_api_info api_info;
  415. bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
  416. if (profiling_p)
  417. {
  418. prof_info.async = async;
  419. prof_info.async_queue = prof_info.async;
  420. }
  421. gomp_mutex_lock (&acc_dev->lock);
  422. n = lookup_host (acc_dev, hostaddrs[0], sizes[0]);
  423. if (n)
  424. {
  425. d = goacc_map_var_existing (acc_dev, hostaddrs[0], sizes[0], n);
  426. gomp_mutex_unlock (&acc_dev->lock);
  427. }
  428. else
  429. {
  430. const size_t mapnum = 1;
  431. gomp_mutex_unlock (&acc_dev->lock);
  432. goacc_aq aq = get_goacc_asyncqueue (async);
  433. struct target_mem_desc *tgt
  434. = goacc_map_vars (acc_dev, aq, mapnum, hostaddrs, NULL, sizes,
  435. kinds, true, GOMP_MAP_VARS_ENTER_DATA);
  436. assert (tgt);
  437. assert (tgt->list_count == 1);
  438. n = tgt->list[0].key;
  439. assert (n);
  440. assert (n->refcount == 1);
  441. assert (n->dynamic_refcount == 0);
  442. n->dynamic_refcount++;
  443. d = (void *) tgt->tgt_start;
  444. }
  445. if (profiling_p)
  446. {
  447. thr->prof_info = NULL;
  448. thr->api_info = NULL;
  449. }
  450. return d;
  451. }
  452. void *
  453. acc_create (void *h, size_t s)
  454. {
  455. unsigned short kinds[1] = { GOMP_MAP_ALLOC };
  456. return goacc_enter_datum (&h, &s, &kinds, acc_async_sync);
  457. }
  458. void
  459. acc_create_async (void *h, size_t s, int async)
  460. {
  461. unsigned short kinds[1] = { GOMP_MAP_ALLOC };
  462. goacc_enter_datum (&h, &s, &kinds, async);
  463. }
  464. /* acc_present_or_create used to be what acc_create is now. */
  465. /* acc_pcreate is acc_present_or_create by a different name. */
  466. #ifdef HAVE_ATTRIBUTE_ALIAS
  467. strong_alias (acc_create, acc_present_or_create)
  468. strong_alias (acc_create, acc_pcreate)
  469. #else
  470. void *
  471. acc_present_or_create (void *h, size_t s)
  472. {
  473. return acc_create (h, s);
  474. }
  475. void *
  476. acc_pcreate (void *h, size_t s)
  477. {
  478. return acc_create (h, s);
  479. }
  480. #endif
  481. void *
  482. acc_copyin (void *h, size_t s)
  483. {
  484. unsigned short kinds[1] = { GOMP_MAP_TO };
  485. return goacc_enter_datum (&h, &s, &kinds, acc_async_sync);
  486. }
  487. void
  488. acc_copyin_async (void *h, size_t s, int async)
  489. {
  490. unsigned short kinds[1] = { GOMP_MAP_TO };
  491. goacc_enter_datum (&h, &s, &kinds, async);
  492. }
  493. /* acc_present_or_copyin used to be what acc_copyin is now. */
  494. /* acc_pcopyin is acc_present_or_copyin by a different name. */
  495. #ifdef HAVE_ATTRIBUTE_ALIAS
  496. strong_alias (acc_copyin, acc_present_or_copyin)
  497. strong_alias (acc_copyin, acc_pcopyin)
  498. #else
  499. void *
  500. acc_present_or_copyin (void *h, size_t s)
  501. {
  502. return acc_copyin (h, s);
  503. }
  504. void *
  505. acc_pcopyin (void *h, size_t s)
  506. {
  507. return acc_copyin (h, s);
  508. }
  509. #endif
  510. /* Helper function to unmap a single data item. Device lock should be held on
  511. entry, and remains locked on exit. */
  512. static void
  513. goacc_exit_datum_1 (struct gomp_device_descr *acc_dev, void *h, size_t s,
  514. unsigned short kind, splay_tree_key n, goacc_aq aq)
  515. {
  516. assert (kind != GOMP_MAP_DETACH
  517. && kind != GOMP_MAP_FORCE_DETACH);
  518. if ((uintptr_t) h < n->host_start || (uintptr_t) h + s > n->host_end)
  519. {
  520. size_t host_size = n->host_end - n->host_start;
  521. gomp_mutex_unlock (&acc_dev->lock);
  522. gomp_fatal ("[%p,+%d] outside mapped block [%p,+%d]",
  523. (void *) h, (int) s, (void *) n->host_start, (int) host_size);
  524. }
  525. bool finalize = (kind == GOMP_MAP_FORCE_FROM
  526. || kind == GOMP_MAP_DELETE);
  527. assert (n->refcount != REFCOUNT_LINK);
  528. if (n->refcount != REFCOUNT_INFINITY
  529. && n->refcount < n->dynamic_refcount)
  530. {
  531. gomp_mutex_unlock (&acc_dev->lock);
  532. gomp_fatal ("Dynamic reference counting assert fail\n");
  533. }
  534. if (finalize)
  535. {
  536. if (n->refcount != REFCOUNT_INFINITY)
  537. n->refcount -= n->dynamic_refcount;
  538. n->dynamic_refcount = 0;
  539. }
  540. else if (n->dynamic_refcount)
  541. {
  542. if (n->refcount != REFCOUNT_INFINITY)
  543. n->refcount--;
  544. n->dynamic_refcount--;
  545. }
  546. if (n->refcount == 0)
  547. {
  548. bool copyout = (kind == GOMP_MAP_FROM
  549. || kind == GOMP_MAP_FORCE_FROM);
  550. if (copyout)
  551. {
  552. void *d = (void *) (n->tgt->tgt_start + n->tgt_offset
  553. + (uintptr_t) h - n->host_start);
  554. gomp_copy_dev2host (acc_dev, aq, h, d, s);
  555. }
  556. if (aq)
  557. /* TODO We can't do the 'is_tgt_unmapped' checking -- see the
  558. 'gomp_unref_tgt' comment in
  559. <http://mid.mail-archive.com/878snl36eu.fsf@euler.schwinge.homeip.net>;
  560. PR92881. */
  561. gomp_remove_var_async (acc_dev, n, aq);
  562. else
  563. {
  564. size_t num_mappings = 0;
  565. /* If the target_mem_desc represents a single data mapping, we can
  566. check that it is freed when this splay tree key's refcount reaches
  567. zero. Otherwise (e.g. for a 'GOMP_MAP_STRUCT' mapping with
  568. multiple members), fall back to skipping the test. */
  569. for (size_t l_i = 0; l_i < n->tgt->list_count; ++l_i)
  570. if (n->tgt->list[l_i].key
  571. && !n->tgt->list[l_i].is_attach)
  572. ++num_mappings;
  573. bool is_tgt_unmapped = gomp_remove_var (acc_dev, n);
  574. assert (is_tgt_unmapped || num_mappings > 1);
  575. }
  576. }
  577. }
  578. /* Exit a dynamic mapping for a single variable. */
  579. static void
  580. goacc_exit_datum (void *h, size_t s, unsigned short kind, int async)
  581. {
  582. /* No need to call lazy open, as the data must already have been
  583. mapped. */
  584. kind &= 0xff;
  585. struct goacc_thread *thr = goacc_thread ();
  586. struct gomp_device_descr *acc_dev = thr->dev;
  587. if (acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  588. return;
  589. acc_prof_info prof_info;
  590. acc_api_info api_info;
  591. bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
  592. if (profiling_p)
  593. {
  594. prof_info.async = async;
  595. prof_info.async_queue = prof_info.async;
  596. }
  597. gomp_mutex_lock (&acc_dev->lock);
  598. splay_tree_key n = lookup_host (acc_dev, h, s);
  599. /* Non-present data is a no-op: PR92726, RP92970, PR92984. */
  600. if (n)
  601. {
  602. goacc_aq aq = get_goacc_asyncqueue (async);
  603. goacc_exit_datum_1 (acc_dev, h, s, kind, n, aq);
  604. }
  605. gomp_mutex_unlock (&acc_dev->lock);
  606. if (profiling_p)
  607. {
  608. thr->prof_info = NULL;
  609. thr->api_info = NULL;
  610. }
  611. }
  612. void
  613. acc_delete (void *h , size_t s)
  614. {
  615. goacc_exit_datum (h, s, GOMP_MAP_RELEASE, acc_async_sync);
  616. }
  617. void
  618. acc_delete_async (void *h , size_t s, int async)
  619. {
  620. goacc_exit_datum (h, s, GOMP_MAP_RELEASE, async);
  621. }
  622. void
  623. acc_delete_finalize (void *h , size_t s)
  624. {
  625. goacc_exit_datum (h, s, GOMP_MAP_DELETE, acc_async_sync);
  626. }
  627. void
  628. acc_delete_finalize_async (void *h , size_t s, int async)
  629. {
  630. goacc_exit_datum (h, s, GOMP_MAP_DELETE, async);
  631. }
  632. void
  633. acc_copyout (void *h, size_t s)
  634. {
  635. goacc_exit_datum (h, s, GOMP_MAP_FROM, acc_async_sync);
  636. }
  637. void
  638. acc_copyout_async (void *h, size_t s, int async)
  639. {
  640. goacc_exit_datum (h, s, GOMP_MAP_FROM, async);
  641. }
  642. void
  643. acc_copyout_finalize (void *h, size_t s)
  644. {
  645. goacc_exit_datum (h, s, GOMP_MAP_FORCE_FROM, acc_async_sync);
  646. }
  647. void
  648. acc_copyout_finalize_async (void *h, size_t s, int async)
  649. {
  650. goacc_exit_datum (h, s, GOMP_MAP_FORCE_FROM, async);
  651. }
  652. static void
  653. update_dev_host (int is_dev, void *h, size_t s, int async)
  654. {
  655. splay_tree_key n;
  656. void *d;
  657. goacc_lazy_initialize ();
  658. struct goacc_thread *thr = goacc_thread ();
  659. struct gomp_device_descr *acc_dev = thr->dev;
  660. if (acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  661. return;
  662. /* Fortran optional arguments that are non-present result in a
  663. NULL host address here. This can safely be ignored as it is
  664. not possible to 'update' a non-present optional argument. */
  665. if (h == NULL)
  666. return;
  667. acc_prof_info prof_info;
  668. acc_api_info api_info;
  669. bool profiling_p = GOACC_PROFILING_SETUP_P (thr, &prof_info, &api_info);
  670. if (profiling_p)
  671. {
  672. prof_info.async = async;
  673. prof_info.async_queue = prof_info.async;
  674. }
  675. gomp_mutex_lock (&acc_dev->lock);
  676. n = lookup_host (acc_dev, h, s);
  677. if (!n)
  678. {
  679. gomp_mutex_unlock (&acc_dev->lock);
  680. gomp_fatal ("[%p,%d] is not mapped", h, (int)s);
  681. }
  682. d = (void *) (n->tgt->tgt_start + n->tgt_offset
  683. + (uintptr_t) h - n->host_start);
  684. goacc_aq aq = get_goacc_asyncqueue (async);
  685. if (is_dev)
  686. gomp_copy_host2dev (acc_dev, aq, d, h, s, false, /* TODO: cbuf? */ NULL);
  687. else
  688. gomp_copy_dev2host (acc_dev, aq, h, d, s);
  689. gomp_mutex_unlock (&acc_dev->lock);
  690. if (profiling_p)
  691. {
  692. thr->prof_info = NULL;
  693. thr->api_info = NULL;
  694. }
  695. }
  696. void
  697. acc_update_device (void *h, size_t s)
  698. {
  699. update_dev_host (1, h, s, acc_async_sync);
  700. }
  701. void
  702. acc_update_device_async (void *h, size_t s, int async)
  703. {
  704. update_dev_host (1, h, s, async);
  705. }
  706. void
  707. acc_update_self (void *h, size_t s)
  708. {
  709. update_dev_host (0, h, s, acc_async_sync);
  710. }
  711. void
  712. acc_update_self_async (void *h, size_t s, int async)
  713. {
  714. update_dev_host (0, h, s, async);
  715. }
  716. void
  717. acc_attach_async (void **hostaddr, int async)
  718. {
  719. struct goacc_thread *thr = goacc_thread ();
  720. struct gomp_device_descr *acc_dev = thr->dev;
  721. goacc_aq aq = get_goacc_asyncqueue (async);
  722. struct splay_tree_key_s cur_node;
  723. splay_tree_key n;
  724. if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  725. return;
  726. gomp_mutex_lock (&acc_dev->lock);
  727. cur_node.host_start = (uintptr_t) hostaddr;
  728. cur_node.host_end = cur_node.host_start + sizeof (void *);
  729. n = splay_tree_lookup (&acc_dev->mem_map, &cur_node);
  730. if (n == NULL)
  731. {
  732. gomp_mutex_unlock (&acc_dev->lock);
  733. gomp_fatal ("struct not mapped for acc_attach");
  734. }
  735. gomp_attach_pointer (acc_dev, aq, &acc_dev->mem_map, n, (uintptr_t) hostaddr,
  736. 0, NULL, false);
  737. gomp_mutex_unlock (&acc_dev->lock);
  738. }
  739. void
  740. acc_attach (void **hostaddr)
  741. {
  742. acc_attach_async (hostaddr, acc_async_sync);
  743. }
  744. static void
  745. goacc_detach_internal (void **hostaddr, int async, bool finalize)
  746. {
  747. struct goacc_thread *thr = goacc_thread ();
  748. struct gomp_device_descr *acc_dev = thr->dev;
  749. struct splay_tree_key_s cur_node;
  750. splay_tree_key n;
  751. struct goacc_asyncqueue *aq = get_goacc_asyncqueue (async);
  752. if (thr->dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  753. return;
  754. gomp_mutex_lock (&acc_dev->lock);
  755. cur_node.host_start = (uintptr_t) hostaddr;
  756. cur_node.host_end = cur_node.host_start + sizeof (void *);
  757. n = splay_tree_lookup (&acc_dev->mem_map, &cur_node);
  758. if (n == NULL)
  759. {
  760. gomp_mutex_unlock (&acc_dev->lock);
  761. gomp_fatal ("struct not mapped for acc_detach");
  762. }
  763. gomp_detach_pointer (acc_dev, aq, n, (uintptr_t) hostaddr, finalize, NULL);
  764. gomp_mutex_unlock (&acc_dev->lock);
  765. }
  766. void
  767. acc_detach (void **hostaddr)
  768. {
  769. goacc_detach_internal (hostaddr, acc_async_sync, false);
  770. }
  771. void
  772. acc_detach_async (void **hostaddr, int async)
  773. {
  774. goacc_detach_internal (hostaddr, async, false);
  775. }
  776. void
  777. acc_detach_finalize (void **hostaddr)
  778. {
  779. goacc_detach_internal (hostaddr, acc_async_sync, true);
  780. }
  781. void
  782. acc_detach_finalize_async (void **hostaddr, int async)
  783. {
  784. goacc_detach_internal (hostaddr, async, true);
  785. }
  786. /* Some types of (pointer) variables use several consecutive mappings, which
  787. must be treated as a group for enter/exit data directives. This function
  788. returns the last mapping in such a group (inclusive), or POS for singleton
  789. mappings. */
  790. static int
  791. find_group_last (int pos, size_t mapnum, size_t *sizes, unsigned short *kinds)
  792. {
  793. unsigned char kind0 = kinds[pos] & 0xff;
  794. int first_pos = pos;
  795. switch (kind0)
  796. {
  797. case GOMP_MAP_TO_PSET:
  798. if (pos + 1 < mapnum
  799. && (kinds[pos + 1] & 0xff) == GOMP_MAP_ATTACH)
  800. return pos + 1;
  801. while (pos + 1 < mapnum
  802. && (kinds[pos + 1] & 0xff) == GOMP_MAP_POINTER)
  803. pos++;
  804. /* We expect at least one GOMP_MAP_POINTER (if not a single
  805. GOMP_MAP_ATTACH) after a GOMP_MAP_TO_PSET. */
  806. assert (pos > first_pos);
  807. break;
  808. case GOMP_MAP_STRUCT:
  809. pos += sizes[pos];
  810. break;
  811. case GOMP_MAP_POINTER:
  812. case GOMP_MAP_ALWAYS_POINTER:
  813. /* These mappings are only expected after some other mapping. If we
  814. see one by itself, something has gone wrong. */
  815. gomp_fatal ("unexpected mapping");
  816. break;
  817. case GOMP_MAP_ATTACH:
  818. break;
  819. default:
  820. /* GOMP_MAP_ALWAYS_POINTER can only appear directly after some other
  821. mapping. */
  822. if (pos + 1 < mapnum)
  823. {
  824. unsigned char kind1 = kinds[pos + 1] & 0xff;
  825. if (kind1 == GOMP_MAP_ALWAYS_POINTER)
  826. return pos + 1;
  827. }
  828. /* We can have a single GOMP_MAP_ATTACH mapping after a to/from
  829. mapping. */
  830. if (pos + 1 < mapnum
  831. && (kinds[pos + 1] & 0xff) == GOMP_MAP_ATTACH)
  832. return pos + 1;
  833. /* We can have zero or more GOMP_MAP_POINTER mappings after a to/from
  834. (etc.) mapping. */
  835. while (pos + 1 < mapnum
  836. && (kinds[pos + 1] & 0xff) == GOMP_MAP_POINTER)
  837. pos++;
  838. }
  839. return pos;
  840. }
  841. /* Map variables for OpenACC "enter data". We can't just call
  842. goacc_map_vars once, because individual mapped variables might have
  843. "exit data" called for them at different times. */
  844. static void
  845. goacc_enter_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
  846. void **hostaddrs, size_t *sizes,
  847. unsigned short *kinds, goacc_aq aq)
  848. {
  849. gomp_mutex_lock (&acc_dev->lock);
  850. for (size_t i = 0; i < mapnum; i++)
  851. {
  852. splay_tree_key n;
  853. size_t group_last = find_group_last (i, mapnum, sizes, kinds);
  854. bool struct_p = false;
  855. size_t size, groupnum = (group_last - i) + 1;
  856. switch (kinds[i] & 0xff)
  857. {
  858. case GOMP_MAP_STRUCT:
  859. {
  860. size = (uintptr_t) hostaddrs[group_last] + sizes[group_last]
  861. - (uintptr_t) hostaddrs[i];
  862. struct_p = true;
  863. }
  864. break;
  865. case GOMP_MAP_ATTACH:
  866. size = sizeof (void *);
  867. break;
  868. default:
  869. size = sizes[i];
  870. }
  871. n = lookup_host (acc_dev, hostaddrs[i], size);
  872. if (n && struct_p)
  873. {
  874. for (size_t j = i + 1; j <= group_last; j++)
  875. {
  876. struct splay_tree_key_s cur_node;
  877. cur_node.host_start = (uintptr_t) hostaddrs[j];
  878. cur_node.host_end = cur_node.host_start + sizes[j];
  879. splay_tree_key n2
  880. = splay_tree_lookup (&acc_dev->mem_map, &cur_node);
  881. if (!n2
  882. || n2->tgt != n->tgt
  883. || n2->host_start - n->host_start
  884. != n2->tgt_offset - n->tgt_offset)
  885. {
  886. gomp_mutex_unlock (&acc_dev->lock);
  887. gomp_fatal ("Trying to map into device [%p..%p) structure "
  888. "element when other mapped elements from the "
  889. "same structure weren't mapped together with "
  890. "it", (void *) cur_node.host_start,
  891. (void *) cur_node.host_end);
  892. }
  893. }
  894. /* This is a special case because we must increment the refcount by
  895. the number of mapped struct elements, rather than by one. */
  896. if (n->refcount != REFCOUNT_INFINITY)
  897. n->refcount += groupnum - 1;
  898. n->dynamic_refcount += groupnum - 1;
  899. }
  900. else if (n && groupnum == 1)
  901. {
  902. void *h = hostaddrs[i];
  903. size_t s = sizes[i];
  904. if ((kinds[i] & 0xff) == GOMP_MAP_ATTACH)
  905. {
  906. gomp_attach_pointer (acc_dev, aq, &acc_dev->mem_map, n,
  907. (uintptr_t) h, s, NULL, false);
  908. /* OpenACC 'attach'/'detach' doesn't affect structured/dynamic
  909. reference counts ('n->refcount', 'n->dynamic_refcount'). */
  910. }
  911. else
  912. goacc_map_var_existing (acc_dev, h, s, n);
  913. }
  914. else if (n && groupnum > 1)
  915. {
  916. assert (n->refcount != REFCOUNT_INFINITY
  917. && n->refcount != REFCOUNT_LINK);
  918. for (size_t j = i + 1; j <= group_last; j++)
  919. if ((kinds[j] & 0xff) == GOMP_MAP_ATTACH)
  920. {
  921. splay_tree_key m
  922. = lookup_host (acc_dev, hostaddrs[j], sizeof (void *));
  923. gomp_attach_pointer (acc_dev, aq, &acc_dev->mem_map, m,
  924. (uintptr_t) hostaddrs[j], sizes[j], NULL,
  925. false);
  926. }
  927. bool processed = false;
  928. struct target_mem_desc *tgt = n->tgt;
  929. for (size_t j = 0; j < tgt->list_count; j++)
  930. if (tgt->list[j].key == n)
  931. {
  932. /* We are processing a group of mappings (e.g.
  933. [GOMP_MAP_TO, GOMP_MAP_TO_PSET, GOMP_MAP_POINTER]).
  934. Find the right group in the target_mem_desc's variable
  935. list, and increment the refcounts for each item in that
  936. group. */
  937. for (size_t k = 0; k < groupnum; k++)
  938. if (j + k < tgt->list_count
  939. && tgt->list[j + k].key
  940. && !tgt->list[j + k].is_attach)
  941. {
  942. tgt->list[j + k].key->refcount++;
  943. tgt->list[j + k].key->dynamic_refcount++;
  944. }
  945. processed = true;
  946. break;
  947. }
  948. if (!processed)
  949. {
  950. gomp_mutex_unlock (&acc_dev->lock);
  951. gomp_fatal ("dynamic refcount incrementing failed for "
  952. "pointer/pset");
  953. }
  954. }
  955. else if (hostaddrs[i])
  956. {
  957. /* The data is not mapped already. Map it now, unless the first
  958. member in the group has a NULL pointer (e.g. a non-present
  959. optional parameter). */
  960. gomp_mutex_unlock (&acc_dev->lock);
  961. struct target_mem_desc *tgt
  962. = goacc_map_vars (acc_dev, aq, groupnum, &hostaddrs[i], NULL,
  963. &sizes[i], &kinds[i], true,
  964. GOMP_MAP_VARS_ENTER_DATA);
  965. assert (tgt);
  966. gomp_mutex_lock (&acc_dev->lock);
  967. for (size_t j = 0; j < tgt->list_count; j++)
  968. {
  969. n = tgt->list[j].key;
  970. if (n && !tgt->list[j].is_attach)
  971. n->dynamic_refcount++;
  972. }
  973. }
  974. i = group_last;
  975. }
  976. gomp_mutex_unlock (&acc_dev->lock);
  977. }
  978. /* Unmap variables for OpenACC "exit data". */
  979. static void
  980. goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
  981. void **hostaddrs, size_t *sizes,
  982. unsigned short *kinds, goacc_aq aq)
  983. {
  984. gomp_mutex_lock (&acc_dev->lock);
  985. /* Handle "detach" before copyback/deletion of mapped data. */
  986. for (size_t i = 0; i < mapnum; ++i)
  987. {
  988. unsigned char kind = kinds[i] & 0xff;
  989. bool finalize = false;
  990. switch (kind)
  991. {
  992. case GOMP_MAP_FORCE_DETACH:
  993. finalize = true;
  994. /* Fallthrough. */
  995. case GOMP_MAP_DETACH:
  996. {
  997. struct splay_tree_key_s cur_node;
  998. uintptr_t hostaddr = (uintptr_t) hostaddrs[i];
  999. cur_node.host_start = hostaddr;
  1000. cur_node.host_end = cur_node.host_start + sizeof (void *);
  1001. splay_tree_key n
  1002. = splay_tree_lookup (&acc_dev->mem_map, &cur_node);
  1003. if (n == NULL)
  1004. {
  1005. gomp_mutex_unlock (&acc_dev->lock);
  1006. gomp_fatal ("struct not mapped for detach operation");
  1007. }
  1008. gomp_detach_pointer (acc_dev, aq, n, hostaddr, finalize, NULL);
  1009. }
  1010. break;
  1011. default:
  1012. ;
  1013. }
  1014. }
  1015. for (size_t i = 0; i < mapnum; ++i)
  1016. {
  1017. unsigned char kind = kinds[i] & 0xff;
  1018. switch (kind)
  1019. {
  1020. case GOMP_MAP_FROM:
  1021. case GOMP_MAP_FORCE_FROM:
  1022. case GOMP_MAP_TO_PSET:
  1023. case GOMP_MAP_POINTER:
  1024. case GOMP_MAP_DELETE:
  1025. case GOMP_MAP_RELEASE:
  1026. {
  1027. struct splay_tree_key_s cur_node;
  1028. size_t size;
  1029. if (kind == GOMP_MAP_POINTER)
  1030. size = sizeof (void *);
  1031. else
  1032. size = sizes[i];
  1033. cur_node.host_start = (uintptr_t) hostaddrs[i];
  1034. cur_node.host_end = cur_node.host_start + size;
  1035. splay_tree_key n
  1036. = splay_tree_lookup (&acc_dev->mem_map, &cur_node);
  1037. if (n == NULL)
  1038. continue;
  1039. goacc_exit_datum_1 (acc_dev, hostaddrs[i], size, kind, n, aq);
  1040. }
  1041. break;
  1042. case GOMP_MAP_STRUCT:
  1043. /* Skip the 'GOMP_MAP_STRUCT' itself, and use the regular processing
  1044. for all its entries. This special handling exists for GCC 10.1
  1045. compatibility; afterwards, we're not generating these no-op
  1046. 'GOMP_MAP_STRUCT's anymore. */
  1047. break;
  1048. case GOMP_MAP_DETACH:
  1049. case GOMP_MAP_FORCE_DETACH:
  1050. /* OpenACC 'attach'/'detach' doesn't affect structured/dynamic
  1051. reference counts ('n->refcount', 'n->dynamic_refcount'). */
  1052. break;
  1053. default:
  1054. gomp_fatal (">>>> goacc_exit_data_internal UNHANDLED kind 0x%.2x",
  1055. kind);
  1056. }
  1057. }
  1058. gomp_mutex_unlock (&acc_dev->lock);
  1059. }
  1060. static void
  1061. goacc_enter_exit_data_internal (int flags_m, size_t mapnum, void **hostaddrs,
  1062. size_t *sizes, unsigned short *kinds,
  1063. bool data_enter, int async, int num_waits,
  1064. va_list *ap)
  1065. {
  1066. int flags = GOACC_FLAGS_UNMARSHAL (flags_m);
  1067. struct goacc_thread *thr;
  1068. struct gomp_device_descr *acc_dev;
  1069. goacc_lazy_initialize ();
  1070. thr = goacc_thread ();
  1071. acc_dev = thr->dev;
  1072. bool profiling_p = GOACC_PROFILING_DISPATCH_P (true);
  1073. acc_prof_info prof_info;
  1074. if (profiling_p)
  1075. {
  1076. thr->prof_info = &prof_info;
  1077. prof_info.event_type
  1078. = data_enter ? acc_ev_enter_data_start : acc_ev_exit_data_start;
  1079. prof_info.valid_bytes = _ACC_PROF_INFO_VALID_BYTES;
  1080. prof_info.version = _ACC_PROF_INFO_VERSION;
  1081. prof_info.device_type = acc_device_type (acc_dev->type);
  1082. prof_info.device_number = acc_dev->target_id;
  1083. prof_info.thread_id = -1;
  1084. prof_info.async = async;
  1085. prof_info.async_queue = prof_info.async;
  1086. prof_info.src_file = NULL;
  1087. prof_info.func_name = NULL;
  1088. prof_info.line_no = -1;
  1089. prof_info.end_line_no = -1;
  1090. prof_info.func_line_no = -1;
  1091. prof_info.func_end_line_no = -1;
  1092. }
  1093. acc_event_info enter_exit_data_event_info;
  1094. if (profiling_p)
  1095. {
  1096. enter_exit_data_event_info.other_event.event_type
  1097. = prof_info.event_type;
  1098. enter_exit_data_event_info.other_event.valid_bytes
  1099. = _ACC_OTHER_EVENT_INFO_VALID_BYTES;
  1100. enter_exit_data_event_info.other_event.parent_construct
  1101. = data_enter ? acc_construct_enter_data : acc_construct_exit_data;
  1102. enter_exit_data_event_info.other_event.implicit = 0;
  1103. enter_exit_data_event_info.other_event.tool_info = NULL;
  1104. }
  1105. acc_api_info api_info;
  1106. if (profiling_p)
  1107. {
  1108. thr->api_info = &api_info;
  1109. api_info.device_api = acc_device_api_none;
  1110. api_info.valid_bytes = _ACC_API_INFO_VALID_BYTES;
  1111. api_info.device_type = prof_info.device_type;
  1112. api_info.vendor = -1;
  1113. api_info.device_handle = NULL;
  1114. api_info.context_handle = NULL;
  1115. api_info.async_handle = NULL;
  1116. }
  1117. if (profiling_p)
  1118. goacc_profiling_dispatch (&prof_info, &enter_exit_data_event_info,
  1119. &api_info);
  1120. if ((acc_dev->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
  1121. || (flags & GOACC_FLAG_HOST_FALLBACK))
  1122. {
  1123. prof_info.device_type = acc_device_host;
  1124. api_info.device_type = prof_info.device_type;
  1125. goto out_prof;
  1126. }
  1127. if (num_waits)
  1128. goacc_wait (async, num_waits, ap);
  1129. goacc_aq aq = get_goacc_asyncqueue (async);
  1130. if (data_enter)
  1131. goacc_enter_data_internal (acc_dev, mapnum, hostaddrs, sizes, kinds, aq);
  1132. else
  1133. goacc_exit_data_internal (acc_dev, mapnum, hostaddrs, sizes, kinds, aq);
  1134. out_prof:
  1135. if (profiling_p)
  1136. {
  1137. prof_info.event_type
  1138. = data_enter ? acc_ev_enter_data_end : acc_ev_exit_data_end;
  1139. enter_exit_data_event_info.other_event.event_type = prof_info.event_type;
  1140. goacc_profiling_dispatch (&prof_info, &enter_exit_data_event_info,
  1141. &api_info);
  1142. thr->prof_info = NULL;
  1143. thr->api_info = NULL;
  1144. }
  1145. }
  1146. /* Legacy entry point (GCC 11 and earlier). */
  1147. void
  1148. GOACC_enter_exit_data (int flags_m, size_t mapnum, void **hostaddrs,
  1149. size_t *sizes, unsigned short *kinds, int async,
  1150. int num_waits, ...)
  1151. {
  1152. /* Determine if this is an OpenACC "enter data". */
  1153. bool data_enter = false;
  1154. for (size_t i = 0; i < mapnum; ++i)
  1155. {
  1156. unsigned char kind = kinds[i] & 0xff;
  1157. if (kind == GOMP_MAP_POINTER
  1158. || kind == GOMP_MAP_TO_PSET
  1159. || kind == GOMP_MAP_STRUCT)
  1160. continue;
  1161. if (kind == GOMP_MAP_FORCE_ALLOC
  1162. || kind == GOMP_MAP_FORCE_PRESENT
  1163. || kind == GOMP_MAP_ATTACH
  1164. || kind == GOMP_MAP_FORCE_TO
  1165. || kind == GOMP_MAP_TO
  1166. || kind == GOMP_MAP_ALLOC)
  1167. {
  1168. data_enter = true;
  1169. break;
  1170. }
  1171. if (kind == GOMP_MAP_RELEASE
  1172. || kind == GOMP_MAP_DELETE
  1173. || kind == GOMP_MAP_DETACH
  1174. || kind == GOMP_MAP_FORCE_DETACH
  1175. || kind == GOMP_MAP_FROM
  1176. || kind == GOMP_MAP_FORCE_FROM)
  1177. break;
  1178. gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
  1179. kind);
  1180. }
  1181. va_list ap;
  1182. va_start (ap, num_waits);
  1183. goacc_enter_exit_data_internal (flags_m, mapnum, hostaddrs, sizes, kinds,
  1184. data_enter, async, num_waits, &ap);
  1185. va_end (ap);
  1186. }
  1187. void
  1188. GOACC_enter_data (int flags_m, size_t mapnum, void **hostaddrs,
  1189. size_t *sizes, unsigned short *kinds, int async,
  1190. int num_waits, ...)
  1191. {
  1192. va_list ap;
  1193. va_start (ap, num_waits);
  1194. goacc_enter_exit_data_internal (flags_m, mapnum, hostaddrs, sizes, kinds,
  1195. true, async, num_waits, &ap);
  1196. va_end (ap);
  1197. }
  1198. void
  1199. GOACC_exit_data (int flags_m, size_t mapnum, void **hostaddrs,
  1200. size_t *sizes, unsigned short *kinds, int async,
  1201. int num_waits, ...)
  1202. {
  1203. va_list ap;
  1204. va_start (ap, num_waits);
  1205. goacc_enter_exit_data_internal (flags_m, mapnum, hostaddrs, sizes, kinds,
  1206. false, async, num_waits, &ap);
  1207. va_end (ap);
  1208. }
  1209. void
  1210. GOACC_declare (int flags_m, size_t mapnum,
  1211. void **hostaddrs, size_t *sizes, unsigned short *kinds)
  1212. {
  1213. for (size_t i = 0; i < mapnum; i++)
  1214. {
  1215. unsigned char kind = kinds[i] & 0xff;
  1216. if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
  1217. continue;
  1218. switch (kind)
  1219. {
  1220. case GOMP_MAP_ALLOC:
  1221. if (acc_is_present (hostaddrs[i], sizes[i]))
  1222. continue;
  1223. /* FALLTHRU */
  1224. case GOMP_MAP_FORCE_ALLOC:
  1225. case GOMP_MAP_TO:
  1226. case GOMP_MAP_FORCE_TO:
  1227. goacc_enter_exit_data_internal (flags_m, 1, &hostaddrs[i], &sizes[i],
  1228. &kinds[i], true, GOMP_ASYNC_SYNC, 0, NULL);
  1229. break;
  1230. case GOMP_MAP_FROM:
  1231. case GOMP_MAP_FORCE_FROM:
  1232. case GOMP_MAP_RELEASE:
  1233. case GOMP_MAP_DELETE:
  1234. goacc_enter_exit_data_internal (flags_m, 1, &hostaddrs[i], &sizes[i],
  1235. &kinds[i], false, GOMP_ASYNC_SYNC, 0, NULL);
  1236. break;
  1237. case GOMP_MAP_FORCE_DEVICEPTR:
  1238. break;
  1239. case GOMP_MAP_FORCE_PRESENT:
  1240. if (!acc_is_present (hostaddrs[i], sizes[i]))
  1241. gomp_fatal ("[%p,%ld] is not mapped", hostaddrs[i],
  1242. (unsigned long) sizes[i]);
  1243. break;
  1244. default:
  1245. assert (0);
  1246. break;
  1247. }
  1248. }
  1249. }