github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/runtime/go-defer.c (about)

     1  /* go-defer.c -- manage the defer stack.
     2  
     3     Copyright 2009 The Go Authors. All rights reserved.
     4     Use of this source code is governed by a BSD-style
     5     license that can be found in the LICENSE file.  */
     6  
     7  #include <stddef.h>
     8  
     9  #include "runtime.h"
    10  #include "go-alloc.h"
    11  #include "go-panic.h"
    12  #include "go-defer.h"
    13  
    14  /* This function is called each time we need to defer a call.  */
    15  
    16  void
    17  __go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
    18  {
    19    G *g;
    20    struct __go_defer_stack *n;
    21  
    22    g = runtime_g ();
    23    n = runtime_newdefer ();
    24    n->__next = g->defer;
    25    n->__frame = frame;
    26    n->__panic = g->panic;
    27    n->__pfn = pfn;
    28    n->__arg = arg;
    29    n->__retaddr = NULL;
    30    n->__makefunc_can_recover = 0;
    31    n->__special = 0;
    32    g->defer = n;
    33  }
    34  
    35  /* This function is called when we want to undefer the stack.  */
    36  
    37  void
    38  __go_undefer (_Bool *frame)
    39  {
    40    G *g;
    41  
    42    g = runtime_g ();
    43    while (g->defer != NULL && g->defer->__frame == frame)
    44      {
    45        struct __go_defer_stack *d;
    46        void (*pfn) (void *);
    47  
    48        d = g->defer;
    49        pfn = d->__pfn;
    50        d->__pfn = NULL;
    51  
    52        if (pfn != NULL)
    53  	(*pfn) (d->__arg);
    54  
    55        g->defer = d->__next;
    56  
    57        /* This may be called by a cgo callback routine to defer the
    58  	 call to syscall.CgocallBackDone, in which case we will not
    59  	 have a memory context.  Don't try to free anything in that
    60  	 case--the GC will release it later.  */
    61        if (runtime_m () != NULL)
    62  	runtime_freedefer (d);
    63  
    64        /* Since we are executing a defer function here, we know we are
    65  	 returning from the calling function.  If the calling
    66  	 function, or one of its callees, paniced, then the defer
    67  	 functions would be executed by __go_panic.  */
    68        *frame = 1;
    69      }
    70  }
    71  
    72  /* This function is called to record the address to which the deferred
    73     function returns.  This may in turn be checked by __go_can_recover.
    74     The frontend relies on this function returning false.  */
    75  
    76  _Bool
    77  __go_set_defer_retaddr (void *retaddr)
    78  {
    79    G *g;
    80  
    81    g = runtime_g ();
    82    if (g->defer != NULL)
    83      g->defer->__retaddr = __builtin_extract_return_addr (retaddr);
    84    return 0;
    85  }