 +    implementation = _sgx_enclave_configuration,
 +    output_to_genfiles = True,
 +    attrs = {
-+        "prodid": attr.string(default = "0"),
-+        "isvsvn": attr.string(default = "0"),
-+        "stack_max_size": attr.string(default = "0x40000"),
-+        "heap_max_size": attr.string(default = "0x100000"),
-+        "tcs_num": attr.string(default = "10"),
-+        "tcs_policy": attr.string(default = "1"),
++        "prodid": attr.string(
++            default = "0",
++            doc = ("The enclave's ISV (Independent Software Vendor) assigned " +
++                   "Product ID"),
++        ),
++        "isvsvn": attr.string(
++            default = "0",
++            doc = ("The enclave's ISV (Independent Software Vendor) assigned " +
++                   "Security Version Number"),
++        ),
++        "stack_max_size": attr.string(
++            default = "0x40000",
++            doc = "The enclave's maximum stack size in bytes (4KB aligned)",
++        ),
++        "heap_max_size": attr.string(
++            default = "0x100000",
++            doc = "The enclave's maximum heap size in bytes (4KB aligned)",
++        ),
++        # 2 tcs are reserved by the framework, 10 are left for users.
++        "tcs_num": attr.string(
++            default = "12",
++            doc = ("The number of Thread Control Structures allocated for " +
++                   "the enclave"),
++        ),
++        "tcs_policy": attr.string(
++            default = "1",
++            doc = ("The TCS management policy (" +
++                   "0 - The TCS is bound to the untrusted thread, " +
++                   "1 - The TCS is unbound to the untrusted thread)"),
++        ),
 +        # "1" for release enclaves.
-+        "disable_debug": attr.string(default = "0"),
-+        "misc_select": attr.string(default = "0"),
-+        "misc_mask": attr.string(default = "0xffffffff"),
++        "disable_debug": attr.string(
++            default = "0",
++            doc = ("Indicates whether launching the enclave in debug mode is " +
++                   "disabled"),
++        ),
++        "provision_key": attr.string(
++            default = "0",
++            doc = ("Indicates whether the enclave has access to the " +
++                   "Provisioning Key and the Provisioning Seal Key"),
++        ),
++        "misc_select": attr.string(
++            default = "0",
++            doc = "The desired Extended SSA frame feature (must be 0)",
++        ),
++        "misc_mask": attr.string(
++            default = "0xffffffff",
++            doc = "A mask indicating which bits in misc_select are enforced",
++        ),
 +    },
 +)
 +

 {
     if ((proc != ECMD_RUN_SWITCHLESS_TWORKER) &&  (proc < 0))
     {
@@ -63,15 +63,15 @@
 }
 

     {
         threads.push_back(*it);
     }
@@ -309,7 +317,7 @@
     //try to get tcs from thread cache
     se_thread_id_t thread_id = get_thread_id();
     CTrustThread *trust_thread = get_bound_thread(thread_id);
-    if(NULL != trust_thread  && m_utility_thread != trust_thread)
+    if(NULL != trust_thread && m_utility_thread != trust_thread && m_user_utility_thread != trust_thread)
     {
         return trust_thread;
     }
@@ -334,7 +342,7 @@
     LockGuard lock(&m_thread_mutex);
     CTrustThread *trust_thread = NULL;
     bool is_special_ecall = (ecall_cmd == ECMD_INIT_ENCLAVE) || (ecall_cmd == ECMD_UNINIT_ENCLAVE) ;
-    
+    bool is_user_utility = (ecall_cmd == ECMD_UTILITY);
 
     if(is_special_ecall == true)
     {
@@ -357,6 +365,21 @@
             trust_thread = _acquire_thread();
         }
     }
+    else if (is_user_utility)
+    {
+        if (m_user_utility_thread)
+        {
+            if (m_user_utility_thread_in_use.exchange(true))
+            {
+                return NULL;
+            }
+            trust_thread = m_user_utility_thread;
+            assert(trust_thread != NULL);
+        } else
+        {
+            trust_thread = _acquire_thread();
+        }
+    }
     else
     {
         trust_thread = _acquire_thread();
@@ -392,6 +415,10 @@
 //Do nothing for bind mode, the tcs is always bound to a thread.
 void CTrustThreadPool::release_thread(CTrustThread * const trust_thread)
 {
+    if (trust_thread == m_user_utility_thread)
+    {
+        m_user_utility_thread_in_use = false;
+    }
     LockGuard lock(&m_thread_mutex);
     trust_thread->decrease_ref();
     return;
@@ -533,7 +560,7 @@
 
     //if free list is NULL, recycle tcs.
     //get thread id set of current process
