Multi-version asynchronous dynamic software update system and method for applications with multiple threads

A method and system for using multiple versions of a software component, includes storing, in memory, a first function table that points to executable code in the memory for functions from a first version of the software component, and storing, in the memory, a second function table that points to executable code in the memory for functions from a second version of the software component, referencing the first function table, when running a first application thread, to execute the functions from the first version of the software component; and referencing the second function table, when running a second application thread that is active concurrently with the first application thread, to execute the functions from the second version of the software component.

TECHNICAL FIELD

The present invention relates to multi-version asynchronous dynamic software updates for applications with multiple threads.

BACKGROUND

Computer programs and applications commonly make use of a plugin style architecture in which a base computer program relies on other software components, known alternatively as plugins, add-ins, add-ons or extensions, that can add specific features to the base computer program. Examples of plug-ins are the storage engine Application Program Interfaces (APIs) underneath Relational Database Services (RDS) such as MySQL. Such APIs are typically exposed as function pointer tables in shared libraries. Another example of a plugin architecture is the controller code that runs on a base station unit (BU) in a Cloud-Radio Access Network (Cloud-RAN).

In the plugin environment, several co-existing program threads can be accessing the same plugin components, which can introduce challenges when updating plugin components. Dynamic Software Update (DSU) procedures have been developed to allow code and data updates such as critical security patches to be applied to a software component such as a plugin without downtime. For example, Ksplice (Ksplice: Automatic Rebootless Kernel Updates; Jeff Arnold and M. Frans Kaashoek; Massachusetts Institute of Technology; https://pdos.csail.mit.edu/papers/ksplice:eurosys.pdf) describes a DSU procedure for applying patches into the Linux kernel. Another example is the Kitsune system (Kitsune: Efficient, General-purpose Dynamic Software Updating for C; Christopher M. Hayden, Edward K. Smith, Michail Denchev, Michael Hicks, Jeffrey S. Foster; University of Maryland, College Park, USA; https://www.cs.umd.edu/˜tedks/papers/2012-oopsla-kitsune.pdf). Both of these procedures require quiescing the system in some way before the update can be performed. In the present disclosure, DSU procedures that require the system to be quiesced before a dynamic update can be applied are referred to as “synchronous” DSU procedures. Synchronous DSU ensures that an update in the system state will be observed by all threads consistently. However, Synchronous DSU can be disadvantageous in some systems because the overhead of quiescing the system can increase as the number of active threads increases.

Accordingly, there is a need for a DSU procedure and system in which software updates can be applied to a software component that does not require quiescing the system.

SUMMARY

The present disclosure presents a dynamic software update (DSU) method and system for multi-threaded applications. The DSU system that is described is asynchronous in that the update can be done on a thread by thread basis with each thread independently updating to a new software component version at an opportune time for that particular thread. Accordingly, the application environment does not have to be quiesced before a dynamic update can be applied.

According to a first example aspect is a method for using a software component. The method includes storing, in memory, a first function table that points to executable code in the memory for functions from a first version of the software component, and storing, in the memory, a second function table that points to executable code in the memory for functions from a second version of the software component. The method also includes referencing the first function table, when running a first application thread, to execute the functions from the first version of the software component; and referencing the second function table, when running a second application thread that is active concurrently with the first application thread, to execute the functions from the second version of the software component.

In some embodiments of the first aspect, the first function table and the second function table are stored as objects in a linked list. In some embodiments the method includes setting a global pointer to point to the first function table, copying the global pointer to a local pointer of the first application thread, wherein the first application thread uses its local pointer to reference the first function table, setting the global pointer to point to the second function table, and copying the global pointer to a local pointer of the second application thread, wherein the second application thread uses its local pointer to reference the second function table.

In some examples, the method includes copying the global pointer to the local pointer of the first application thread to update the first application thread to the functions from the second version of the software component. In some configurations, the method includes de-allocating memory for the first version of the software component when no application threads have a local pointer that references the first function table. In some examples, the method includes monitoring for a signal indicating that the second version of the software component is available, wherein the second function table is stored in the memory and the global pointer is set to point to the second function table after detecting the signal.

In some embodiments of the first aspect, a pointer is included in the second function table that points to the first function table. In some embodiments the application is a Go program and the running threads are goroutines.

According to a second aspect is a processing system configured to support a live software component update. The system includes a processing device, a memory associated with the processing device, and a non-transient storage for storing instructions. When loaded to the memory and executed by the processing device, the instructions cause the processing system to: store, in the memory, a first function table that points to executable code in the memory for functions from a first version of a software component; store, in the memory, a second function table that points to executable code in the memory for functions from a second version of the software component; reference the first function table, when running a first thread of an application, to execute the functions from the first version of the software component; and reference the second function table, when running a second thread of the application that is active concurrently with the first thread, to execute the functions from the second version of the software component.

In some examples of the second aspect, the instructions cause the processing system to reference the first function table, when running the first thread of an application, by: setting a global pointer to point to the first function table when the first function table is stored; and setting, when the first thread is created, a local pointer of the first thread equal to the global pointer; and cause the processing system to reference the second function table, when running the second thread of the application, by: setting the global pointer to point to the second function table when the second function table is stored; and subsequently setting, when the second thread is created, a local pointer of the second thread equal to the global pointer. In some examples, the instructions cause the processing system to, for each of the threads of the application, asynchronously set the local pointer of the thread to a current value of the global pointer if the local pointer is not equal to the current value of the global pointer. In some examples, the processing system maintains a counter for each of the stored function tables that identifies a number of active threads having local pointers that point to the function table, and deletes stored function tables that are not pointed at by the local pointers of any active threads.

In some examples according to the second aspect, the function tables are stored in the memory as a linked list of shared objects and may be stored in a cache region of the memory allocated to the application.

According to a third example aspect is a computer program product comprising a non-transient storage medium storing instructions to cause a processing device to: store, in memory allocated to a program, a first function table that points to executable code in the memory for functions from a first version of a software component; store, in the memory, a second function table that points to executable code in the memory for functions from a second version of the software component; reference the first function table, when running a first application thread, to execute the functions from the first version of the software component; and reference the second function table, when running a second application thread that is active concurrently with the first application thread, to execute the functions from the second version of the software component.

According to a fourth aspect is a method for supporting multiple update versions of a software component that is used by multiple threads of an application. The method includes storing, in memory allocated to the application, executable code for a first version of the software component; storing, in the memory, executable code for an update version of the software component; running, by a first thread of the application, the executable code for the first version of the software component; and running, by a second thread of the application that is active concurrently with the first thread, the executable code for the update version of the software component.

In some examples of the forth aspect, executable code for multiple versions of the software component are concurrently stored in the memory and each version has one or more associated callable functions, the method also including: storing, in the memory, a respective function table for each version, each function table including pointers to respective locations in the memory of the functions associated with the version; setting a global pointer value to point to the respective function table for the version that is the most recent of the versions; and setting, at different times for a plurality of threads of the application, a respective thread local pointer equal to the global pointer value; wherein running the executable code comprises calling one or more of the functions based on the function table that is pointed to by the thread local pointer of a calling thread.

According to a fifth aspect is a processing system configured to support a live software component update. The processing system includes a processing device, a memory associated with the processing device, and a non-transient storage for storing instructions. The instructions, when loaded to the memory and executed by the processing device, cause the processing system to: store, in a portion of the memory allocated to the application, executable code for a first version of the software component; store, in the memory, executable code for an update version of the software component; run, by a first thread of the application, the executable code for the first version of the software component; and run, by a second thread of the application that is active concurrently with the first thread, the executable code for the update version of the software component.

DETAILED DESCRIPTION OF ILLUSTRATIVE EMBODIMENTS

The present disclosure presents a dynamic software update (DSU) system for updating software components such as plugins used by multi-threaded applications. The DSU system is asynchronous in that the update can be done on a thread by thread basis during an application's runtime with each thread independently updating to a new plugin version at an opportune time for that particular thread. Accordingly, the application environment does not have to be quiesced before a dynamic update can be applied. Although the presently described asynchronous DSU system can be implemented in different environments, Standard C programming language and Go programming language syntax are used in this description to illustrate example embodiments. An example embodiment will first be described in the context of a C programming language environment.

FIG. 1schematically represents an architecture of an asynchronous DSU (A-DSU) system10according to example embodiments, along with a multi-threaded main application113and a software component such as a plugin111that is used by the main application113. In particular,FIG. 1schematically represents software and data components stored in RAM memory118assigned by an operating system to main application113. Memory assigned by an operating system to the main application113is referred to below as application memory118. In the illustrated embodiment, A-DSU system10is implemented through A-DSU Support Library120that exposes one or more application program interface (API) components A-DSU API100. A-DSU Support Library120includes the code, data and bookkeeping elements required to support the DSU operations described in this disclosure. The software and data files required for A-DSU Support Library120may, for example, be provided to users as one or more library files. As will be explained in greater detail below, during system operation the components of A-DSU Support Library120are used to facilitate the updates of a software component such as plugin111that is used by main application113. In example embodiments, A-DSU Support Library120is allocated memory within the application memory118as required to load the executable code and reference files required for A-DSU Support Library120.

Add-on software components such a plugins are typically a collection of files and functions in a shared object dynamic library and are conventionally exposed as function pointers in a shared library. A common example of plugins that are commonly used by a main application include APIs (including, for example well documented APIs such as the storage engine APIs underneath Relational Database Services (RDS) such as MySQL, and the controller code APIs that run on base station units (BU) in a Cloud-Radio Access Network (Cloud-RAN)). InFIG. 1, multiple versions of plugin111are represented, including an initial or first version of plugin111(represented as Version_1.so110(1)), an updated second version of plugin111(represented as Version_2.so110(2)) and an Nth update version (represented as Version_N.so110(N)). The plugin update versions become available during the runtime of main application113. Plugin versions are generically referred to as Version.so.

During runtime, main application113can access shared library software components such as plugin111that are dynamically loaded (for example by using the “dlopen” command) into the application memory118. When the plugin111is first loaded, an operating system allocates address space for the plugin within the application memory118, and loads the plugin's initial version executable code (shown as Version_1.so110(1) inFIG. 1) into the allocated address space of the main application's memory118. The main application113will typically create multiple threads116(1) to116(N) (grouped together as threads116under “Main Application113” inFIG. 1) that each share access to plugin111's executable code Version_1.so110(1).

In example embodiments, the main application113includes code elements to make the program compatible with A-DSU API100and other elements of the A-DSU Support Library120. In one example, this is done by including calls to various A-DSU API functions100in the main application113. As shown inFIG. 1, three A-DSU-API functions included as part of the A-DSU API100and exposed by A-DSU Support Library120are represented as: LoadInitialVersion102; LoadNextVersion106; and PickUpLatestVersion108. As will be explained in greater detail below, the function LoadInitialVersion102is used to load an initial plugin code version into memory118and set up bookkeeping elements to support future plugin code version updates. The function LoadNextVersion106is used to load and support updated plugin versions. The function PickUpLatestVersion108is used to transition a running thread116to the updated executing plugin version.

In example embodiments, a call to A-DSU function LoadInitialVersion102is included in main application113to load the first plugin Version_1.so110(1). In one example, the LoadInitialVersion102function call is included in main application113in place of a “dlopen” call, and takes the form LoadInitialVersion (lib string, flag int). The parameter “lib” specifies the location in persistent storage (for example a system hard drive) of the code for plugin Version_1.so110(1). The parameter “flag” identifies types of plugin update monitoring. In one example, the flag parameter be set to the following values: flag=“0”, which indicates no update monitoring is required because updates will be manually triggered by main application113calling the A_DSU function LoadNextVersion directly; flag=“SIG” which indicates that updates will be triggered by an interrupt signal such as SIGUSR1 or SIGUSR2, and flag=“FS”, which indicates that an update will be triggered by notification of a change to a specified file (for example, via inotify).

As noted above, when called by the main application113, A-DSU function LoadInitialVersion102loads initial plugin code Version_1.so110(1) into memory118allocated by the operating system to main application113. As part of the loading process, the LoadInitialVersion102function sets up bookkeeping elements to support future plugin code version updates. In this regard, in one example embodiment A-DSU function LoadInitialVersion102executes the following actions: (1) dynamically loads Version_1.so110(1) into application memory118; (2) causes a version record, represented inFIG. 1as version record122(1) for Version_1.so110(1), to be created in A-DSU Support Library120in application memory118; and (3) initiates a monitoring thread. Reference number122is used herein to generically refer to one or more version records122(1) to122(N). In an example embodiment version records122are each implemented as a C-style struct.

The purpose of the version record122(1) is to provide a function table that identifies all the functions exposed by plugin Version_1.so110(1) and provides pointers to the functions in application memory118. In this regard, the version record122(1) includes a function table124, which as shown inFIG. 1identifies and points to a plurality of functions (func0, func1, . . . ). LoadInitialVersion102also sets a global pointer variable “globalPtr” in A-DSU Support Library120that points to the newly created version record122(1), and initializes a set of metadata126associated with the plugin Version_1.so110(1). In the illustrated example, metadata126includes: “version”—a variable that identifies the version of the plugin111that is represented by the version record122(1); “*dynlib”—points to the shared library for version 1.so as it resides in memory118; “count”—a thread reference count variable that identifies the number of program threads116,116that are currently using Version_1.so110(1); “pthread_mutex-tlock”—a lock used by threads to facilitate updating of the variable “count”; and “struct node_t*next”—which points to the previous version record122(i). In the illustrated example of A-DSU Support Library120the A-DSU version records122are implemented as a linked list. In some examples, different hardware specific locking mechanisms may be used in place of pthread_mutex_tlock and unlock.

With respect to monitoring thread creation, the function LoadInitialVersion102also performs any initializations required to support the type of program update monitoring identified by the “flag” variable in the call to LoadInitialVersion102. For example, in the case of flag=“SIG”, LoadInitialVersion102will install a signal handler to monitor for a signal such as SIGUSR1 or SIGUSR2 (referred to herein as SIGUSR) to trigger a program update. In some example implementations, a monitor thread121is created within the A-DSU Support Library120to monitor for a SIGUSR signal, and perform garbage collection as described below.

While Version_1.so110(1) is running, threads116may be created by main application113. In example embodiments, each time a new thread116is created it is assigned a “localPtr” in its thread local storage (TLS) in application memory118that is used to point to the current version record122. In the case of a newly loaded program, the “localPTR” for the initial thread116(1) will initially be null. When the initial thread116(1) is created a call is made to A-DSU PickUpLatestVersion function108in the form of: PickUpLatestVersion (LocalPtr). The calling thread116(1) passes its null “localPtr” value as an input parameter to the PickUpLatestVersion function108, which is configured to return a pointer to the most recently created version record122and also perform bookkeeping functions by updating the metadata126of the current and previous version records122. In this regard, reference204inFIG. 2shows a state diagram representation of the A-DSU PickUpLatestVersion function108. As shown in state214, the PickUpLatestVersion function108compares the “currLocalPtr” value it receives from the calling thread116(for example thread116(1)) against the “globalPtr”. In the case thread116(1), the “curLocalPtr” value is null and thus will not be equal to the value of the globalPtr. This results in the PickUpLatestVersion function108performing actions indicated in state218. These actions include setting “currLocalPtr” equal to “globalPtr” (currLocalPtr=globalPtr), increasing the version “count” in metadata124by one to track the total number of threads that are using the current plugin Version_1.so110(1) (atomic_inc (currLocalPtr)), and returning the currLocalPtr value to the calling thread116to use as its “localPtr” value.

When calling a function, each thread116(1) to116(N) references the function table124of the version record122that the thread's “localPtr” points to. Accordingly, it the case of a newly loaded initial plugin Version_1.so110(1) for which no updates have occurred, the “globalPtr” value and the localPtr values for the respective threads116(1) to116(N) will all point to the version record122(1) for Version_1.so110(1), which in turn identifies all the functions that are included in Version_1.so110(1) and the locations of the executable code for such functions in the main application memory118.

The system10supports live updates for multiple update versions of plugin111, enabling updates from Version_1.so110(1) to Version_2.so110(2) and so on to version.so110(N) as such updates become available. The operation of system10to implement a live update from plugin111Version_1.so110(1) to Version_2.so110(2) will now be described with reference toFIGS. 1 and 2. The presently described example concerns a scenario in which the changes require one or more selected plugin functions (func0, func1, etc.) to be updated that do not read or write to global variables.

In this regard, a plugin update is initiated (by a system operator, for example) when Version_2.so110(2) of plugin111becomes available. In some examples, Version_2.so110(2) includes updates of one or more of the plugin functions func0, func1, and may include additional functions.

In an example embodiment, a system operator triggers the update signal SIGUSR when the updated plugin Version_2.so110(2) is available for dynamic loading. As noted above, in one embodiment a monitor thread121of the A-DSU support library120is configured to monitor for the SIGUSR signal, and in this regard,FIG. 2includes a state diagram202that represents actions taken by the monitoring thread121. As indicated in state diagram202, the monitor thread121remains in an event loop state210until the SIGUSR signal is detected, at which time the A-DSU function LoadNextVersion106is called as indicated by state212. The LoadNextVersion function106performs the actions shown in state212. As indicated by the statement “dlopen and create new Version Record”, Version_2.so110(2) is dynamically loaded into application memory118and a corresponding version record122(2) struct for Version_2.so110(2) is created in the A-DSU Support Library120. At such time, multiple versions of plugin111are present in the application memory118(Version_1.so110(1) and Version_2.so110(2)) and multiple corresponding version records (version record122(1) and122(2)) are present in A-DSU Support Library120. The new version record122(2) also includes a function table124that identifies and points to the functions of Version_2.so110(2).

A-DSU function LoadNextVersion106also updates the “globalPtr” to point to the newly created version record122(2) in A-DSU Support Library120, as indicated by statement “set globalPtr to new Version Record” in state212. As indicated by the statement “atomic-dec old Version Record's reference count” in state212, the pthread_mutex_tlock of old version record122(1) is locked for the time when the variable “count” in the old version record122(1) metadata126is decreased by 1. Correspondingly, as indicated by the statement “atomic-inc new Version Record's reference count” in state212, the pthread_mutex_tlock of new version record122(2) is locked for the time when the variable “count” in the new version record122(2) metadata126is increased to 1. Other metadata126variables in version record122(2) are populated as follows: “version”—is set as Version_2.so110(2); “*dynlib”—points to a shared library in which the functions func0, func1, etc. are located in application memory118; and “struct node_t*next” is set to point to the last version record in A-DSU Support Library120that preceded the newly loaded version record122(2) and that is still active, which in the present example is version record122(1) in A-DSU Support Library120. Accordingly, in example embodiments, A-DSU Support Library120includes a linked list of version record objects that each contain a respective function table124. Each version record object includes a link to the version record object that most recently preceded it and is still active (i.e. still has a “count” greater than zero). As indicated above, version records122(1),122(2) can be implemented as C-style struct objects in example embodiments.

The “LoadNextVersion” function106(including the steps shown in state212) will be performed each time an update occurs for plugin111. As noted above, although a SIGUSR signal was used to signal the availability of Version_2.so110(2), in example embodiments the “LoadNextVersion” function106can be triggered by alternative mechanisms, including for example a manual trigger in which an explicit call to “LoadNextVersion” function106is included in the code of main application113.

It will be appreciated that upon completion of the “LoadNextVersion” function106, the variable “globalPtr” that is used by system10to point to the current version record122will point to the most recent version record (for example version record122(2)), whereas the threads116will still be working with a prior version record (for example version record122(1)) as indicated by their respective “localPtr” variables. Each thread116will continue to independently execute its corresponding codeuntil it encounters a “PickUpLatestVersion” function call in the code. In this regard, when a programmer is configuring the main application113to make the program A-DSU compatible, the programmer will select opportune locations to insert “PickUpLatestVersion” function calls in the program code. In particular, an opportune location for such a calls will ideally be at a point in the code when a transition to an updated plugin111Version.so can be performed seamlessly from the perspective of the thread116.

Referring again to the state diagram204inFIG. 2, a call to the A-DSU function “PickUpLatestVersion”108by a thread116copies the thread's “localPtr” value to the variable “currLocalPtr” of function108, which is then compared (state214) to the “globalPtr” value. If the values are equal, the thread116is using the current version record122and corresponding current plugin Version.so and no update is required at the thread level. In such case, “PickUpLatestVersion” function108simply returns the value of curreLocalPtr to the calling thread116, as indicated in state216. However, if the “globalPtr” and the “currLocalPtr” values don't match, then a thread level plugin version update is required and the actions shown in state218are performed. In the example of a thread level update from Version_1.so110(1) to Version_2.so110(2), the following occurs: (1) As indicated by the statement “atomic_dec (currLocalPtr), the pthread_mutex_tlock of previous version record122(1) is momentarily locked and the variable “int count” in the previous version record122(1) metadata126is decreased by 1; (2) As indicated by the statement “currlocalPtr=globalPtr” the currlocalPtr value is updated to equal the globalPtr, which points to the current version record122(2) for updated plugin Version_2.so110(2); (3) As indicated by the statement “atomic_inc (currLocalPtr), the, the pthread_mutex_tlock of the new version record122(2) is momentarily locked and the variable “int count” in the new version record122(2) metadata126is increased by 1; and (4) the new value of “currLocalPtr” is returned to the calling thread116as the new “localPtr” value for the thread.

Accordingly, at the completion of the A-DSU function “PickUpLatestVersion”108, the calling thread116is updated to the new plugin Version_2.so110(2). Each of the threads116will respectively call the A-DSU function “PickUpLatestVersion”108at the time that is appropriate for that thread, so a synchronous quiescing of all threads is not required. Rather, individual threads116asynchronously update to the new Version_2.so110(2).

Although the above description specifically referenced an update from Version_1.so110(1) to Version_2.so110(2), the same procedure is performed to update to subsequent version updates. At any given time, it is possible that the executable code and corresponding version records122for multiple plugin version updates will be active in application memory118, with different update versions being used concurrently by different threads116.

Referring to state diagram202inFIG. 2, in example embodiments the monitor thread121is configured to periodically traverse the linked list of version records122that are included in A-DSU Support Library120to look for versions records122where “count”=0 and perform a garbage collection (GC) operation220on such objects. For example, in the situation where all threads116have updated from Version_1.so110(1) to Version_2.so110(2), the variable “count” in metadata126of version record122(1) will have a value of “zero”. Accordingly, GC operation220will close (for example using the dlclose operation in C) Version_1.so110(1) to release memory. GC operation220can also release portions of memory that store the version record122(1). As noted above, the “struct node_t*next” variable in metadata126is used to point to the next version record in A-DSU Support Library120that preceded the current version record and that is still active. Accordingly, in the example of a completed update from Version_1.so110(1) to Version_2.so110(2), the variable “struct node_t*next” in metadata126for version record122(2) would be set to null once the version record122(1) has a int count of 0. In at least some examples where a plurality of program updates have occurred, it is possible that a prior version of executable code and corresponding version record from an update prior to the previous update version could still be active even when one or more intervening version records have been closed. For example, version record122(1) could still be used by some threads, even when version record122(2) no longer exists, in which case the “struct node_t*next” variable in metadata126for the current version record (for example version record122(N)) will be set to point to the next still active preceding version record122(1).

It will thus be appreciated that the update system10provides an environment in which multiple threads116can be asynchronously migrated to updated executable plugin code without requiring the main application to be quiesced or stopped. Each thread116is able to migrate at an update point in code execution that has been selected as most convenient for that particular thread. Such an A-DSU system can be particularly useful for system configuration changes including database administrative changes. Also, such an A-DSU system can be useful to support long-term connections during a webserver update. In the webserver use case, there can often be hundreds of threads concurrently running to handle user requests, and the presently described A-DSU system can facilitate the update without requiring a system wide quiescing and the resources required to support such a quiescing.

Although described above in the context of a C-language programming environment, A-DSU-system10can also be implemented in other environments, including for example the Go programming language. In some example embodiments, the Go implementation is similar to that described above in respect of C, subject to the two following differences. Given the relative ease with which lightweight worker threads (known as Goroutines) are spawned in Go, in some example embodiments each Goroutine thread uses the same plugin version.so throughout its existence from the time it is spawned until the time that it finishes running, even if an executable code update occurs during the duration of the Goroutine. Accordingly, unlike the C implementation, in some example embodiments individual Goroutine threads will not migrate from one plugin version to another while running. Furthermore, because Go runtime manages garbage collection, the A-DSU specific coding required to implement garbage collection (GC) in the Go environment is reduced compared to that required for a C implementation. In some example embodiments, DSU-system10can alternatively be configured to support active migration of a Goroutine thread from one plugin version to another in a similar manner to that described above in respect of C-implementation.

In this regard,FIG. 3provides two state diagrams302,304that correspond to a Go implemented embodiment of A-DSU system10. Referring toFIGS. 1 and 3, similar to the C-implemented embodiment, in the illustrated Go embodiment, calling the API function A-DSU LoadInitialVersion102causes initial plugin Version_1.so110(1) to be loaded into application memory118and the creation of new version record122(1) for Version_1.so110(1) in A-DSU Support Library120. The “globalPtr” value is set to point to the newly created version record122(1). In the Go environment, much of the metadata126is maintained by Go runtime, including the thread “count” value, and a garbage collection finalizer is associated with each newly created version record object. Each version record object is automatically deallocated by its associated garbage collection finalizer when it is no longer referenced by any threads.

Referring to state diagram302, the function A-DSU LoadInitialVersion102also starts a Goroutine monitor thread116that operates in an event loop state310and monitors for signal SIGUSR that indicates when an updated version is available for loading into application memory118. When the SIGUSR signal is detected, a call to the A-DSU LoadNextVersion function occurs, as indicated in state312, resulting in the loading of the new plugin version (for example, Version_2.so110(2)) (as indicted by the statement “dlopen”) and creation of a new version record (for example version record122(2)) that includes function pointers for the newly loaded version. The “globalPtr” value is updated to point at the newly opened version record122(2). Go runtime automatically takes care of garbage collection for old version records whose “count” value goes to zero. In particular, when the number of threads using a version.so goes to zero, garbage collection is triggered and the associated Go finalizer is invoked. As a result, Version_1.so is closed leading to appropriate cleanup including removal of Version_1.so from the application memory118.

Referring to state diagram304, each new Goroutine thread116that is started (state314) has the current “globalPtr” value copied to its associated “localPtr” (state316). The Goroutine thread116will use that localPtr value (and hence the corresponding version record and functions) throughout the entire time that the Goroutine thread116is running. Thus, depending on the “globalPtr” value over time, different Goroutine threads116that start at different times but which run concurrently can point to different version records122and thus use different plugin versions versioni.so110(i), however each Goroutine thread116will continue throughout its existence to use the same pluigin version that it was initially assigned. As suggested above, an assumption is made that each Goroutine thread116will have a relatively short running time such that the use of single version for that running time will typically not be problematic. Once a Goroutine thread116finishes, its localPtr goes out of scope, releasing the thread's reference to the corresponding version record shared object122. Go runtime tracks and updates the thread “count” for each version record as new Goroutine threads reference the version record and running Goroutines expire.

FIG. 4is a schematic diagram of an example processing system400, which may be used to implement the methods and systems disclosed herein. The processing system400may be a server or base station, for example, or any suitable computing system. Other processing systems suitable for implementing examples described in the present disclosure may be used, which may include components different from those discussed below. AlthoughFIG. 4shows a single instance of each component, there may be multiple instances of each component in the processing system400and the processing system400could be implemented using parallel and/or distributed systems.

The processing system400may include one or more processing devices405, such as a processor, a microprocessor, an application-specific integrated circuit (ASIC), a field-programmable gate array (FPGA), a dedicated logic circuitry, or combinations thereof. The processing system400may also include one or more optional input/output (I/O) interfaces410, which may enable interfacing with one or more appropriate input devices435and/or output devices440. The processing system400may include one or more network interfaces415for wired or wireless communication with a network (e.g., an intranet, the Internet, a P2P network, a WAN and/or a LAN) or other node. The network interfaces415may include one or more interfaces to wired networks and wireless networks. Wired networks may make use of wired links (e.g., Ethernet cable). Wireless networks, where they are used, may make use of wireless connections transmitted over antenna445. The network interfaces415may provide wireless communication via one or more transmitters or transmit antennas and one or more receivers or receive antennas, for example. In this example, a single antenna445is shown, which may serve as both transmitter and receiver. However, in other examples there may be separate antennas for transmitting and receiving. In embodiments in which the processing system is a network controller, such as an SDN Controller, there may be no wireless interface, and antenna445may not be present in all embodiments. The processing system400may also include one or more storage units420, which may include a mass storage unit such as a solid state drive, a hard disk drive, a magnetic disk drive and/or an optical disk drive.

The processing system400may include one or more memories425, which may include a volatile or non-volatile memory (e.g., a flash memory, a random access memory (RAM), and/or a read-only memory (ROM)). The non-transitory memories425(as well as storage420) may store instructions for execution by the processing devices405, such as to carry out methods such as those described in the present disclosure. The memories425may include other software instructions, such as for implementing an operating system and other applications/functions. In some examples, one or more data sets and/or modules may be provided by an external memory (e.g., an external drive in wired or wireless communication with the processing system400) or may be provided by a transitory or non-transitory computer-readable medium. Examples of non-transitory computer readable media include a RAM, a ROM, an erasable programmable ROM (EPROM), an electrically erasable programmable ROM (EEPROM), a flash memory, a CD-ROM, or other portable memory storage.

There may be a bus430providing communication among components of the processing system400. The bus430may be any suitable bus architecture including, for example, a memory bus, a peripheral bus or a video bus. Optional input devices435(e.g., a keyboard, a mouse, a microphone, a touchscreen, and/or a keypad) and output devices440(e.g., a display, a speaker and/or a printer) are shown as external to the processing system400, and connected to optional I/O interface410. In other examples, one or more of the input devices435and/or the output devices440may be included as a component of the processing system400. Embodiments in which processing system400is a network controller may lack a physical I/O interface410, and instead may be a so-called headless server for which all interactions are carried out through a connection to network interface415.

In example embodiments, a processing system400configured to implement A-DSU system10may be configured to maintain information or files that include the object code for A-DSU API100in memory425or storage420or a combination thereof. In example embodiments, application memory118allocated by an operating system for A-DSU Support Library120, main application113and plugin111is part of memory425. In some implementations, the memory425that is used for A-DSU Support Library120, including version records122, is the L1 cache assigned to by operating system software to processing device405to support the main application113.

Thus, in an example embodiment, processing system400is configured to support multiple running threads116of an application through live plugin updates. Non-transient storage420stores instructions that when loaded to the memory425and executed by the processing device405cause the processing system to: store, for each executable code update version_i.so110(i) of a software component (such as a plugin) loaded into the application memory118, an associated function table124that points to the updated versioni.so110(i) code in the memory; set a global pointer (globalPtr) to point to the function table124associated with the most recently loaded versioni.so110(i); set, when an application thread116is created, a local pointer (localPtr) of the application thread116equal to the global pointer (globalPtr); and use, for each application thread116, the versioni.so110(i) associated with the function table124pointed to by the application thread's local pointer (localPtr).

FIG. 5shows method steps that correspond to an example embodiment. The steps shown in dashed lines correspond to one non-limiting option for supporting the steps shown in in solid lines. In the example ofFIG. 5, a first function table124(included in first version record122(1)) is stored that points to executable code in the memory425for functions (func0, func1 . . . ) from a first version (Version_1.so110(1)) of a software component (Action502). A global pointer (globalPtr) is set to point to the first function table124(Action504) and the global pointer (globalPtr) is copied to a local pointer (localPtr) for a first application thread116(1) (Action506). A second function table124(included in version record122(2)) is then stored that points to executable code in the memory425for functions from a second version (Version_2.so110(2)) of the program (Action508). The global pointer (globalPtr) is updated to point to the second function table124(Action510) and updated global pointer (globalPtr) is copied to a local pointer (localPtr) for a second application thread116(2) (Action512). At such time, the localPtr for the first application thread116(1) still points to the first function table124in version record122(1), so the first function table is referenced when running the first application thread116(1), to execute the functions from the first version of the software component (Action514). However co-existing second application thread116(2) has a localPtr that points to the second function table124in version record122(2), so the second function table is referenced when running the second application thread116(2), to execute the functions from the second version of the software component (Action516).

FIG. 6shows, according to a further example embodiment, method steps for supporting multiple update versions of a software component (such as a plugin111) is used by multiple threads116of an application113. The method includes: storing, in memory118allocated to the application113, executable code for a first version (for example Version_1.so110(1)) of the software component111(Action602); storing, in the memory118, executable code for an update version (for example, Version_2.so110(2)) of the software component (Action604); running, by a first thread (for example thread116(1)) of the application113, the executable code for the first version of the software component (Action606); and running, by a second thread (for example thread116(2)) of the application113that is active concurrently with the first thread, the executable code for the update version of the software component111(Action608).

Certain adaptations and modifications of the described embodiments can be made. Therefore, the above discussed embodiments are considered to be illustrative and not restrictive. While this invention has been described with reference to illustrative embodiments, this description is not intended to be construed in a limiting sense. Various modifications and combinations of the illustrative embodiments, as well as other embodiments of the invention, will be apparent to persons skilled in the art upon reference to the description. It is therefore intended that the appended claims encompass any such modifications or embodiments.