A good memory is inferior to a bad pen. The study to be done today is about the code in the Bionic directory.
The first thing you need to see is the _ERRNO.C code.
Volatile int* __errno (void) { return & (volatile int*) __get_tls ()) [Tls_slot_errno];}
As you can see from the above, a pointer to the int type is returned.
The volatile keyword is a type modifier that declares a type variable that can be changed by factors unknown to the compiler, such as the operating system, hardware, or other threads. Because the access register is faster than RAM, the compiler generally makes optimizations to reduce access to external RAM. When you encounter a variable declared by this keyword, the compiler will no longer optimize the code that accesses the variable, providing stable access to the special address.
Volatile is meant to be "variable", but it is more appropriate to translate it into "direct access to the original memory address." "Volatile" is caused by external factors, like multi-threading, interruption, and so on, not because the variable modified with volatile is "volatile", if there is no external cause, that is, using volatile definition, it will not change.
The second need to speak of this code of _SET_ERRONO.C.
This function will eventually be called by the system.
Also in this function, even if the data exceeds the bounds, it is still not considered a mistake. Because in Linux, the error code will not exceed 131.
if (n > -256) { return __set_errno (-n); } else { return n; }
OpenBSD is a multi-platform, 4.4BSD-based Unix-like operating system that is one of the three free operating systems from BSD (the other two are NetBSD and FreeBSD) and is known as the safest operating system in the world.
The next thing to learn is ARC4RANDOM.C.
Static pthread_mutex_t _arc4_lock = pthread_mutex_initializer; #define _arc4_lock () Pthread_mutex_lock (&_arc4_lock) #define _arc4_unlock () Pthread_mutex_unlock (&_arc4_lock)
The purpose of defining a lock is to protect the global variables in the file.
Just be aware that this file is used to generate random numbers between 0~1.
Next look at the Basename.c class.
In this file, there is only one function that returns a string.
if (bname = = NULL) { bname = (char *) malloc (maxpathlen); if (bname = = null) return (null); }
There is a clear allocation of storage space.
Next you see this file is Bionic_clone this file.
Mainly look at the Clone method inside.
Intclone (int (*FN) (void *), void *child_stack, int flags, void* arg, ...) { va_list args; int *parent_tidptr = NULL; void *new_tls = NULL; int *child_tidptr = NULL; int ret; /* Extract Optional Parameters-they is cummulative * /Va_start (args, arg); if (Flags & (clone_parent_settid| clone_settls| Clone_child_settid) { parent_tidptr = va_arg (args, int*); } if (Flags & (clone_settls| Clone_child_settid) { new_tls = va_arg (args, void*); } if (Flags & Clone_child_settid) { child_tidptr = va_arg (args, int*); } Va_end (args); RET = __bionic_clone (Flags, Child_stack, Parent_tidptr, New_tls, Child_tidptr, FN, ARG); return ret;}
1. Parameter list
2, the parent thread and the child thread pointer, and the definition of the returned value.
The next file to be viewed is the clearenv file.
int clearenv (void) { char **p = environ; if (P! = null) {for (; *p; ++p) *p = NULL; } return 0;}
It can be seen from above that environ is a pointer to a carton pointer, and can also be understood as a two-dimensional array of strings.
Note the following method in the Dlmalloc file:
Static size_t release_unused_segments (mstate m) {size_t released = 0; Msegmentptr pred = &m->seg; Msegmentptr SP = pred->next; while (sp! = 0) {char* base = sp->base; size_t size = sp->size; Msegmentptr next = sp->next; if (is_mmapped_segment (SP) &&!is_extern_segment (sp)) {Mchunkptr p = align_as_chunk (base); size_t psize = chunksize (p); /* Can Unmap If first chunk holds entire segment and not pinned * * if (!cinuse (p) && (char*) p + psize >= b ASE + size-top_foot_size) {tchunkptr TP = (tchunkptr) p; ASSERT (Segment_holds (SP, (char*) SP)); if (p = = M->DV) {M->DV = 0; m->dvsize = 0; } else {Unlink_large_chunk (M, TP); } if (Call_munmap (base, size) = = 0) {released + = size; M->footprint-= size; /* Unlink obsoleted record */sp = pred; Sp->next = Next; } else {/* BACK out if cannot unmap */Insert_large_chunk (M, TP, psize); }}} pred = SP; SP = Next; } return released;}
The main concern in Pthread-timers is the definition of one of the following structures:
struct Thr_timer { thr_timer_t* next; /* Next in the free list */ timer_t & nbsp id; /* Timer_id_none iff free or dying */ clockid_t & nbsp; clock; pthread_t thread; pthread_attr_t attributes; thr_timer_func_t callback; sigval_t value; /* The following is used to communicate between * th e timer thread and the timer_xxx () functions */ pthread_mutex_t & nbsp; mutex; /* Lock */ pthread_cond_t cond ; /* Signal a state change to thread */ int volatile & nbsp; done; /* Set by Timer_ Delete */ int volatile stopped; /* set by _start_stop () */ struct Timespec volatile expires; & nbsp /* Next expiration time, or 0 */ struct Timespec volatile period; /* Reload Valu E, or 0 */ int volatile overruns; /* Current number of overruns */};1. Pointer to the current idle queue
2. Define the associated thread semaphore and the corresponding callback function
3. Define some variables that call each other between the threads of a time slice and some functions
Android Kernel source Bionic directory of the source of the learning notes