OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / gthr-posix95.h
1 /* Threads compatibility routines for libgcc2 and libobjc.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 <http://www.gnu.org/licenses/>.  */
25
26 #ifndef GCC_GTHR_POSIX_H
27 #define GCC_GTHR_POSIX_H
28
29 /* POSIX threads specific definitions.
30    Easy, since the interface is just one-to-one mapping.  */
31
32 #define __GTHREADS 1
33
34 /* Some implementations of <pthread.h> require this to be defined.  */
35 #ifndef _REENTRANT
36 #define _REENTRANT 1
37 #endif
38
39 #include <pthread.h>
40 #include <unistd.h>
41
42 typedef pthread_key_t __gthread_key_t;
43 typedef pthread_once_t __gthread_once_t;
44 typedef pthread_mutex_t __gthread_mutex_t;
45 typedef pthread_cond_t __gthread_cond_t;
46
47 /* POSIX like conditional variables are supported.  Please look at comments
48    in gthr.h for details. */
49 #define __GTHREAD_HAS_COND      1
50
51 typedef struct {
52   long depth;
53   pthread_t owner;
54   pthread_mutex_t actual;
55 } __gthread_recursive_mutex_t;
56
57 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
58 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
59 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
60 #define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
61
62 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
63 # define __gthrw(name) \
64   static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
65 # define __gthrw_(name) __gthrw_ ## name
66 #else
67 # define __gthrw(name)
68 # define __gthrw_(name) name
69 #endif
70
71 __gthrw(pthread_once)
72 __gthrw(pthread_key_create)
73 __gthrw(pthread_key_delete)
74 __gthrw(pthread_getspecific)
75 __gthrw(pthread_setspecific)
76 __gthrw(pthread_create)
77 __gthrw(pthread_cancel)
78 __gthrw(pthread_self)
79
80 __gthrw(pthread_mutex_init)
81 __gthrw(pthread_mutex_destroy)
82 __gthrw(pthread_mutex_lock)
83 __gthrw(pthread_mutex_trylock)
84 __gthrw(pthread_mutex_unlock)
85 __gthrw(pthread_mutexattr_init)
86 __gthrw(pthread_mutexattr_destroy)
87
88 __gthrw(pthread_cond_broadcast)
89 __gthrw(pthread_cond_wait)
90
91 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
92 /* Objective-C.  */
93 __gthrw(pthread_cond_destroy)
94 __gthrw(pthread_cond_init)
95 __gthrw(pthread_cond_signal)
96 __gthrw(pthread_exit)
97 #ifdef _POSIX_PRIORITY_SCHEDULING
98 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
99 __gthrw(sched_get_priority_max)
100 __gthrw(sched_get_priority_min)
101 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
102 #endif /* _POSIX_PRIORITY_SCHEDULING */
103 __gthrw(sched_yield)
104 __gthrw(pthread_attr_destroy)
105 __gthrw(pthread_attr_init)
106 __gthrw(pthread_attr_setdetachstate)
107 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
108 __gthrw(pthread_getschedparam)
109 __gthrw(pthread_setschedparam)
110 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
111 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
112
113 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
114
115 /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
116    -pthreads is not specified.  The functions are dummies and most return an
117    error value.  However pthread_once returns 0 without invoking the routine
118    it is passed so we cannot pretend that the interface is active if -pthreads
119    is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
120    we need to play the usual game with weak symbols.  On Solaris 10 and up, a
121    working interface is always exposed.  On FreeBSD 6 and later, libc also
122    exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
123    to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
124    which means the alternate __gthread_active_p below cannot be used there.  */
125
126 #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
127
128 static volatile int __gthread_active = -1;
129
130 static void
131 __gthread_trigger (void)
132 {
133   __gthread_active = 1;
134 }
135
136 static inline int
137 __gthread_active_p (void)
138 {
139   static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
140   static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
141
142   /* Avoid reading __gthread_active twice on the main code path.  */
143   int __gthread_active_latest_value = __gthread_active;
144
145   /* This test is not protected to avoid taking a lock on the main code
146      path so every update of __gthread_active in a threaded program must
147      be atomic with regard to the result of the test.  */
148   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
149     {
150       if (__gthrw_(pthread_once))
151         {
152           /* If this really is a threaded program, then we must ensure that
153              __gthread_active has been set to 1 before exiting this block.  */
154           __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
155           __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
156           __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
157         }
158
159       /* Make sure we'll never enter this block again.  */
160       if (__gthread_active < 0)
161         __gthread_active = 0;
162
163       __gthread_active_latest_value = __gthread_active;
164     }
165
166   return __gthread_active_latest_value != 0;
167 }
168
169 #else /* neither FreeBSD nor Solaris */
170
171 static inline int
172 __gthread_active_p (void)
173 {
174   static void *const __gthread_active_ptr
175     = __extension__ (void *) &__gthrw_(pthread_cancel);
176   return __gthread_active_ptr != 0;
177 }
178
179 #endif /* FreeBSD or Solaris */
180
181 #else /* not SUPPORTS_WEAK */
182
183 /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
184    calls in shared flavors of the HP-UX C library.  Most of the stubs
185    have no functionality.  The details are described in the "libc cumulative
186    patch" for each subversion of HP-UX 11.  There are two special interfaces
187    provided for checking whether an application is linked to a pthread
188    library or not.  However, these interfaces aren't available in early
189    libc versions.  We also can't use pthread_once as some libc versions
190    call the init function.  So, we use pthread_create to check whether it
191    is possible to create a thread or not.  The stub implementation returns
192    the error number ENOSYS.  */
193
194 #if defined(__hppa__) && defined(__hpux__)
195
196 #include <errno.h>
197
198 static volatile int __gthread_active = -1;
199
200 static void __gthread_active_init (void) __attribute__((noinline));
201 static void
202 __gthread_active_init (void)
203 {
204   static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
205   size_t __s;
206
207   __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
208   if (__gthread_active < 0)
209     {
210       pthread_default_stacksize_np (0, &__s);
211       __gthread_active = __s ? 1 : 0;
212     }
213   __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
214 }
215
216 static inline int
217 __gthread_active_p (void)
218 {
219   /* Avoid reading __gthread_active twice on the main code path.  */
220   int __gthread_active_latest_value = __gthread_active;
221
222   /* This test is not protected to avoid taking a lock on the main code
223      path so every update of __gthread_active in a threaded program must
224      be atomic with regard to the result of the test.  */
225   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
226     {
227       __gthread_active_init ();
228       __gthread_active_latest_value = __gthread_active;
229     }
230
231   return __gthread_active_latest_value != 0;
232 }
233
234 #else /* not hppa-hpux */
235
236 static inline int
237 __gthread_active_p (void)
238 {
239   return 1;
240 }
241
242 #endif /* hppa-hpux */
243
244 #endif /* SUPPORTS_WEAK */
245
246 #ifdef _LIBOBJC
247
248 /* This is the config.h file in libobjc/ */
249 #include <config.h>
250
251 #ifdef HAVE_SCHED_H
252 # include <sched.h>
253 #endif
254
255 /* Key structure for maintaining thread specific storage */
256 static pthread_key_t _objc_thread_storage;
257 static pthread_attr_t _objc_thread_attribs;
258
259 /* Thread local storage for a single thread */
260 static void *thread_local_storage = NULL;
261
262 /* Backend initialization functions */
263
264 /* Initialize the threads subsystem.  */
265 static inline int
266 __gthread_objc_init_thread_system (void)
267 {
268   if (__gthread_active_p ())
269     {
270       /* Initialize the thread storage key.  */
271       if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
272         {
273           /* The normal default detach state for threads is
274            * PTHREAD_CREATE_JOINABLE which causes threads to not die
275            * when you think they should.  */
276           if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
277               && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
278                                               PTHREAD_CREATE_DETACHED) == 0)
279             return 0;
280         }
281     }
282
283   return -1;
284 }
285
286 /* Close the threads subsystem.  */
287 static inline int
288 __gthread_objc_close_thread_system (void)
289 {
290   if (__gthread_active_p ()
291       && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
292       && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
293     return 0;
294
295   return -1;
296 }
297
298 /* Backend thread functions */
299
300 /* Create a new thread of execution.  */
301 static inline objc_thread_t
302 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
303 {
304   objc_thread_t thread_id;
305   pthread_t new_thread_handle;
306
307   if (!__gthread_active_p ())
308     return NULL;
309
310   if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
311     thread_id = (objc_thread_t) new_thread_handle;
312   else
313     thread_id = NULL;
314
315   return thread_id;
316 }
317
318 /* Set the current thread's priority.  */
319 static inline int
320 __gthread_objc_thread_set_priority (int priority)
321 {
322   if (!__gthread_active_p ())
323     return -1;
324   else
325     {
326 #ifdef _POSIX_PRIORITY_SCHEDULING
327 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
328       pthread_t thread_id = __gthrw_(pthread_self) ();
329       int policy;
330       struct sched_param params;
331       int priority_min, priority_max;
332
333       if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
334         {
335           if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
336             return -1;
337
338           if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
339             return -1;
340
341           if (priority > priority_max)
342             priority = priority_max;
343           else if (priority < priority_min)
344             priority = priority_min;
345           params.sched_priority = priority;
346
347           /*
348            * The solaris 7 and several other man pages incorrectly state that
349            * this should be a pointer to policy but pthread.h is universally
350            * at odds with this.
351            */
352           if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
353             return 0;
354         }
355 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
356 #endif /* _POSIX_PRIORITY_SCHEDULING */
357       return -1;
358     }
359 }
360
361 /* Return the current thread's priority.  */
362 static inline int
363 __gthread_objc_thread_get_priority (void)
364 {
365 #ifdef _POSIX_PRIORITY_SCHEDULING
366 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
367   if (__gthread_active_p ())
368     {
369       int policy;
370       struct sched_param params;
371
372       if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
373         return params.sched_priority;
374       else
375         return -1;
376     }
377   else
378 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
379 #endif /* _POSIX_PRIORITY_SCHEDULING */
380     return OBJC_THREAD_INTERACTIVE_PRIORITY;
381 }
382
383 /* Yield our process time to another thread.  */
384 static inline void
385 __gthread_objc_thread_yield (void)
386 {
387   if (__gthread_active_p ())
388     __gthrw_(sched_yield) ();
389 }
390
391 /* Terminate the current thread.  */
392 static inline int
393 __gthread_objc_thread_exit (void)
394 {
395   if (__gthread_active_p ())
396     /* exit the thread */
397     __gthrw_(pthread_exit) (&__objc_thread_exit_status);
398
399   /* Failed if we reached here */
400   return -1;
401 }
402
403 /* Returns an integer value which uniquely describes a thread.  */
404 static inline objc_thread_t
405 __gthread_objc_thread_id (void)
406 {
407   if (__gthread_active_p ())
408     return (objc_thread_t) __gthrw_(pthread_self) ();
409   else
410     return (objc_thread_t) 1;
411 }
412
413 /* Sets the thread's local storage pointer.  */
414 static inline int
415 __gthread_objc_thread_set_data (void *value)
416 {
417   if (__gthread_active_p ())
418     return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
419   else
420     {
421       thread_local_storage = value;
422       return 0;
423     }
424 }
425
426 /* Returns the thread's local storage pointer.  */
427 static inline void *
428 __gthread_objc_thread_get_data (void)
429 {
430   if (__gthread_active_p ())
431     return __gthrw_(pthread_getspecific) (_objc_thread_storage);
432   else
433     return thread_local_storage;
434 }
435
436 /* Backend mutex functions */
437
438 /* Allocate a mutex.  */
439 static inline int
440 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
441 {
442   if (__gthread_active_p ())
443     {
444       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
445
446       if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
447         {
448           objc_free (mutex->backend);
449           mutex->backend = NULL;
450           return -1;
451         }
452     }
453
454   return 0;
455 }
456
457 /* Deallocate a mutex.  */
458 static inline int
459 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
460 {
461   if (__gthread_active_p ())
462     {
463       int count;
464
465       /*
466        * Posix Threads specifically require that the thread be unlocked
467        * for __gthrw_(pthread_mutex_destroy) to work.
468        */
469
470       do
471         {
472           count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
473           if (count < 0)
474             return -1;
475         }
476       while (count);
477
478       if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
479         return -1;
480
481       objc_free (mutex->backend);
482       mutex->backend = NULL;
483     }
484   return 0;
485 }
486
487 /* Grab a lock on a mutex.  */
488 static inline int
489 __gthread_objc_mutex_lock (objc_mutex_t mutex)
490 {
491   if (__gthread_active_p ()
492       && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
493     {
494       return -1;
495     }
496
497   return 0;
498 }
499
500 /* Try to grab a lock on a mutex.  */
501 static inline int
502 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
503 {
504   if (__gthread_active_p ()
505       && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
506     {
507       return -1;
508     }
509
510   return 0;
511 }
512
513 /* Unlock the mutex */
514 static inline int
515 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
516 {
517   if (__gthread_active_p ()
518       && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
519     {
520       return -1;
521     }
522
523   return 0;
524 }
525
526 /* Backend condition mutex functions */
527
528 /* Allocate a condition.  */
529 static inline int
530 __gthread_objc_condition_allocate (objc_condition_t condition)
531 {
532   if (__gthread_active_p ())
533     {
534       condition->backend = objc_malloc (sizeof (pthread_cond_t));
535
536       if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
537         {
538           objc_free (condition->backend);
539           condition->backend = NULL;
540           return -1;
541         }
542     }
543
544   return 0;
545 }
546
547 /* Deallocate a condition.  */
548 static inline int
549 __gthread_objc_condition_deallocate (objc_condition_t condition)
550 {
551   if (__gthread_active_p ())
552     {
553       if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
554         return -1;
555
556       objc_free (condition->backend);
557       condition->backend = NULL;
558     }
559   return 0;
560 }
561
562 /* Wait on the condition */
563 static inline int
564 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
565 {
566   if (__gthread_active_p ())
567     return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
568                               (pthread_mutex_t *) mutex->backend);
569   else
570     return 0;
571 }
572
573 /* Wake up all threads waiting on this condition.  */
574 static inline int
575 __gthread_objc_condition_broadcast (objc_condition_t condition)
576 {
577   if (__gthread_active_p ())
578     return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
579   else
580     return 0;
581 }
582
583 /* Wake up one thread waiting on this condition.  */
584 static inline int
585 __gthread_objc_condition_signal (objc_condition_t condition)
586 {
587   if (__gthread_active_p ())
588     return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
589   else
590     return 0;
591 }
592
593 #else /* _LIBOBJC */
594
595 static inline int
596 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
597 {
598   if (__gthread_active_p ())
599     return __gthrw_(pthread_once) (__once, __func);
600   else
601     return -1;
602 }
603
604 static inline int
605 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
606 {
607   return __gthrw_(pthread_key_create) (__key, __dtor);
608 }
609
610 static inline int
611 __gthread_key_delete (__gthread_key_t __key)
612 {
613   return __gthrw_(pthread_key_delete) (__key);
614 }
615
616 static inline void *
617 __gthread_getspecific (__gthread_key_t __key)
618 {
619   return __gthrw_(pthread_getspecific) (__key);
620 }
621
622 static inline int
623 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
624 {
625   return __gthrw_(pthread_setspecific) (__key, __ptr);
626 }
627
628 static inline int
629 __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
630 {
631   if (__gthread_active_p ())
632     return __gthrw_(pthread_mutex_destroy) (__mutex);
633   else
634     return 0;
635 }
636
637 static inline int
638 __gthread_mutex_lock (__gthread_mutex_t *__mutex)
639 {
640   if (__gthread_active_p ())
641     return __gthrw_(pthread_mutex_lock) (__mutex);
642   else
643     return 0;
644 }
645
646 static inline int
647 __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
648 {
649   if (__gthread_active_p ())
650     return __gthrw_(pthread_mutex_trylock) (__mutex);
651   else
652     return 0;
653 }
654
655 static inline int
656 __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
657 {
658   if (__gthread_active_p ())
659     return __gthrw_(pthread_mutex_unlock) (__mutex);
660   else
661     return 0;
662 }
663
664 static inline int
665 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
666 {
667   __mutex->depth = 0;
668   __mutex->owner = (pthread_t) 0;
669   return __gthrw_(pthread_mutex_init) (&__mutex->actual, NULL);
670 }
671
672 static inline int
673 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
674 {
675   if (__gthread_active_p ())
676     {
677       pthread_t __me = __gthrw_(pthread_self) ();
678
679       if (__mutex->owner != __me)
680         {
681           __gthrw_(pthread_mutex_lock) (&__mutex->actual);
682           __mutex->owner = __me;
683         }
684
685       __mutex->depth++;
686     }
687   return 0;
688 }
689
690 static inline int
691 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
692 {
693   if (__gthread_active_p ())
694     {
695       pthread_t __me = __gthrw_(pthread_self) ();
696
697       if (__mutex->owner != __me)
698         {
699           if (__gthrw_(pthread_mutex_trylock) (&__mutex->actual))
700             return 1;
701           __mutex->owner = __me;
702         }
703
704       __mutex->depth++;
705     }
706   return 0;
707 }
708
709 static inline int
710 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
711 {
712   if (__gthread_active_p ())
713     {
714       if (--__mutex->depth == 0)
715         {
716            __mutex->owner = (pthread_t) 0;
717            __gthrw_(pthread_mutex_unlock) (&__mutex->actual);
718         }
719     }
720   return 0;
721 }
722
723 static inline int
724 __gthread_cond_broadcast (__gthread_cond_t *__cond)
725 {
726   return __gthrw_(pthread_cond_broadcast) (__cond);
727 }
728
729 static inline int
730 __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
731 {
732   return __gthrw_(pthread_cond_wait) (__cond, __mutex);
733 }
734
735 static inline int
736 __gthread_cond_wait_recursive (__gthread_cond_t *__cond,
737                                __gthread_recursive_mutex_t *__mutex)
738 {
739   return __gthrw_(pthread_cond_wait) (__cond, &__mutex->actual);
740 }
741
742 #endif /* _LIBOBJC */
743
744 #endif /* ! GCC_GTHR_POSIX_H */